z-index在3D卡片切换中无效,因transform等属性会创建新层叠上下文;应改用translateZ()控制Z轴位置,配合scale()实现真实3D层次,并确保父容器设preserve-3d和足够perspective值。
很多人以为用 z-index 控制卡片堆叠顺序,再配合 transform: scale() 做缩放就能实现“层叠切换”,结果动画一动就错乱——这是因为 z-index 只在**同一个层叠上下文(stacking context)内有效**,而一旦给任意卡片加了 transform、opacity 或 filter,它就自动创建了新的层叠上下文,此时父容器的 z-index 对子元素完全失效。
真正起作用的是 **渲染顺序 + transform 的 z 轴偏移**。实操建议:
z-index 控制卡片前后关系,改用 transform: translateZ() 或 transform: scale() + translateZ() 显式控制 Z 轴位置transform: translateZ(100px) 把它“推到最前面”,其余卡片设为 translateZ(-20px) 等负值transform: scale(0.9) 只是等比缩放,视觉上像“退后”,但浏览器不会因此改变绘制顺序或景深效果——它依然在 Z=0 平面上。要让缩放看起来有真实 3D 层次,必须叠加 Z 轴位移:
transform: scale(1.1) translateZ(50px)(更近 + 更大)transform: scale(0.85) translateZ(-30px)(更远 + 更小)scale():单独 scale 会导致卡片边缘像素模糊(尤其是 Chrome),加 translateZ(0) 可触发 GPU 加速并稳定渲染示例关键帧:
立即学习“前端免费学习笔记(深入)”;
@keyframes card-focus { 0% { transform: scale(0.85) translateZ(-30px); opacity: 0.7; } 100% { transform: scale(1.1) translateZ(50px); opacity: 1; }}
直接对 transform 做 transition 没问题,但常见错误是同时过渡 z-index 或 opacity,导致浏览器反复重建层叠上下文,动画掉帧甚至闪动。
transform 和 opacity(二者都支持硬件加速),**不要过渡 z-index、top、left 等触发布局重排的属性**transform: translateZ(0)(哪怕只是 0),避免动画第一帧突然触发合成层创建classList.toggle() 后立刻读 offsetTop —— 这会强制同步布局计算,改用 getComputedStyle().transform 或 requestAnimationFrame 时机iOS Safari 对 translateZ 的处理很保守:当父容器未启用 3D 上下文时,translateZ 可能被静默忽略,导致所有卡片挤在 Z=0 平面,缩放看起来像平面切换而非层叠。
transform-style: preserve-3d 和 perspective: 1000px(值越大,3D 感越平缓)transform: translateZ(0) —— 这会创建新上下文,反而隔离子元素的 Z 轴效果about:config 打开 Web Inspector,检查 computed style 中 transform 是否包含 matrix3d,而不是降级成 matrix
复杂点在于:同一套 CSS,在 Chrome 滚动流畅,在 Safari 可能首帧延迟半秒——这不是代码错,是 WebKit 对 3D 合成层的懒加载策略。最容易被忽略的是 perspective 值过小(如 200px),会让卡片翻转时形变夸张甚至穿帮。