css 卡片 hover 阴影变化太硬怎么办_使用 box shadow 过渡

box-shadow hover 卡顿因重排重绘,应改用 transform + 精简 box-shadow 并指定过渡属性,配合 will-change 或 translateZ(0) 触发 GPU 加速,移动端用 focus-within 或 touch 事件模拟。

box-shadow hover 为什么看起来“卡”

直接写 transition: all 0.3s 看似合理,但 box-shadow 的数值变化(比如从 0 0 0 0 rgba(0,0,0,0) 跳到 0 4px 12px -2px rgba(0,0,0,0.15))会触发浏览器重排+重绘,尤其阴影模糊半径(第三个值)突变时,GPU 渲染不连贯,人眼就感觉“硬”“跳”。

用 transform + filter 替代部分 shadow 效果

真正平滑的过渡依赖硬件加速属性,transformfilter 是首选。把“抬升感”交给 transform: translateY(-2px),把“柔化感”交给 filter: blur(1px)(慎用,仅小范围),而 box-shadow 只保留基础、低开销的投影:

  • hover 前:只用 box-shadow: 0 1px 3px rgba(0,0,0,0.08)
  • hover 时:叠加 transform: translateY(-2px) + box-shadow: 0 4px 12px -2px rgba(0,0,0,0.15)
  • 务必给容器加 will-change: transform(或 transform: translateZ(0))提前触发 GPU 层

只过渡 box-shadow 的特定维度

如果必须用 box-shadow 动画,别用 all,明确指定要过渡的属性,避免意外触发其他 CSS 变化:

card {
  box-shadow: 0 1px 3px rgba(0,0,0,0.08);
  transition: box-shadow 0.25s cubic-bezier(0.2, 0.8, 0.2, 1),
              transform 0.25s cubic-bezier(0.2, 0.8, 0.2, 1);
}

card:hover {
  box-shadow: 0 4px 12px -2px rgba(0,0,0,0.15);
  transform: translateY(-2px);
}

注意:cubic-bezier(0.2, 0.8, 0.2, 1)ease 更柔和,减少初段突兀感;-2px 的 spread-radius(第四个值)能收紧阴影边缘,视觉上更“收得稳”。

移动端 hover 失效?补一层 focus-within 或 JS 模拟

纯 CSS :hover 在触摸设备上不可靠。若卡片可点击,用 :focus-within 更稳妥;若需精确控制,监听 touchstart + touchend 切换 class:

.card {
  transition: box-shadow 0.2s, transform 0.2s;
}

.card.active

, .card:focus-within { box-shadow: 0 4px 12px -2px rgba(0,0,0,0.15); transform: translateY(-2px); }

关键点:不要等用户松手才还原,touchend 后立刻移除 active,否则阴影会卡住;iOS Safari 对 filter: blur() 支持差,优先用 transform + 精简 box-shadow