z-index必须逐层递增且所有图片置于同一relative容器内,用transform3d替代left/top动画,js控制差异化延迟与位移,animation-fill-mode:forwards必设,复位逻辑不可忽略。

z-index 必须逐层递增,否则叠放顺序会错乱——这是洗牌动画最常卡住的地方。
用 position: absolute + z-index 控制初始堆叠顺序
所有图片必须放在同一个 position: relative 容器内,每张图设 position: absolute; top: 0; left: 0; 才能真正重合。z-index 值要从底到顶递增(比如第1张 z-index: 1,第2张 z-index: 2),不是“越小越在上”。浏览器对无 z-index 的同级元素渲染不一致,不能依赖默认层叠。
常见翻车点:
-
z-index全设成0或相同值,结果所有图叠成一团、看不出层次 - 用
order想控制顺序——但只在display: flex容器里有效,对绝对定位无效 - 靠
opacity模拟“底下”的牌——动画一动就穿帮,因为透明度不影响层叠上下文
用 transform: translate3d() 触发硬件加速
洗牌飞出不能用 left/top 动画,否则移动端卡顿明显。必须用 transform,且推荐写成 translate3d(x, y, 0) 显式触发 GPU 加速。
每张图的动画要独立设置,不能统一加在父容器上:
- 给每张
<img>单独加transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1); - 出发时直接改
style.transform,例如:img.style.transform = 'translate3d(-120px, -80px, 0) rotate(-12deg)'; - 避免同时修改
top+left+transform,浏览器会降级为软件渲染
用 JS 控制随机延迟与位移偏移
CSS @keyframes 很难为每张图配不同参数,JS 是更可控的选择。真实洗牌不是完全随机,而是有规律的混乱:顶部几张偏移小、延迟短;底部几张偏移大、延迟长——模拟手抖和纸牌摩擦。
关键逻辑:
- 遍历图片数组,对每张图设不同
setTimeout延迟(如i * 80ms) - 位移范围要有约束,比如
x: (Math.random() - 0.5) * 200,再限制在 ±150px 内,防止飞出视口 - 旋转角度建议控制在 ±15deg 以内,太大会让图片翻转失控
- 别用
Math.random() * 200直接当位移值——有些图真会飞到屏幕外看不见
animation-fill-mode: forwards 必须显式声明
如果用 CSS @keyframes 做飞出动画(而非 JS 改 transform),漏掉 animation-fill-mode: forwards 就会导致动画一结束立刻弹回原位,整个效果报废。
示例写法:
.card:nth-child(1) { animation: flyOut 0.6s cubic-bezier(0.22, 0.61, 0.36, 1) 0.1s forwards; }
@keyframes flyOut {
to { transform: translate3d(-100px, -60px, 0) rotate(-8deg); }
}
注意:延迟值(0.1s)和贝塞尔曲线要配合,否则飞出节奏生硬;forwards 缺一不可。
真正的难点不在“怎么飞”,而在“怎么收”——洗牌后要不要复位?复位是用反向动画还是 JS 重置 transform 和 z-index?这个环节最容易被忽略,但决定了后续能否再次触发洗牌。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











