应使用 transform: translateY() 而非 top/left 移动卡片,避免重排和掉帧;transition 必须写在默认状态;注意父容器 overflow 和移动端 hover 兼容性。

用 transform 而不是 top/left 移动卡片
直接改 top 或 left 会触发浏览器重排(reflow),动画卡顿且无法硬件加速;transform: translateY() 只影响合成层,性能好、更顺滑。
- ✅ 正确做法:
transform: translateY(-8px) - ❌ 避免写法:
top: -8px(即使加了transition也容易掉帧) - 注意:若卡片本身有
position: relative或absolute,不影响transform使用,无需额外调整定位上下文
transition 必须写在默认状态,不是 hover 状态里
过渡效果要定义在元素的常态样式中,否则第一次悬停时没有过渡,只有离开时才有——这是最常被忽略的细节。
card {
transform: translateY(0);
transition: transform 0.3s ease-out;
}
card:hover {
transform: translateY(-12px);
}
- ⚠️ 错误示范:
card:hover { transition: transform 0.3s; }→ 第一次 hover 没动画 -
ease-out比ease更适合“弹起”感;想更轻盈可用cubic-bezier(0.22, 0.61, 0.36, 1) - 别只写
transition: all 0.3s,它会把所有变化都过渡,可能意外拖慢颜色、阴影等属性
避免因父容器 overflow: hidden 切掉悬停位移
卡片上移后如果超出父容器边界,会被裁剪——尤其常见于网格布局或卡片列表中。
- 检查父级是否设了
overflow: hidden,临时改成overflow: visible测试是否被截断 - 稳妥方案:给父容器加一点
padding-top(比如padding-top: 12px),预留移动空间 - 或者用
will-change: transform提前提示浏览器优化(仅在必要时加,别滥用)
移动端悬停无效?得补 :focus-within 或 JS fallback
CSS :hover 在触摸设备上基本不触发(iOS Safari 尤其严格),纯靠 CSS 无法可靠响应“点击即悬停”。
立即学习“前端免费学习笔记(深入)”;
- 简单兼容:给卡片加
tabindex="0",再用card:focus-within模拟(需配合键盘操作) - 真实场景建议:用
touchstart+classList.toggle()控制一个.is-hovered类,CSS 写card.is-hovered规则 - 别依赖
:active做悬停替代——它只在按下的瞬间生效,松手就消失










