z-index 不支持过渡,因其为离散整数属性,浏览器无法插值计算;真正可过渡的是 opacity 和 transform;模拟层级渐进需用 opacity + visibility + 静态 z-index 组合控制。

transition 里写 z-index 没反应?它根本不能过渡
直接说结论:z-index 是一个离散的整数属性,浏览器不支持对它的插值计算,所以加了 transition: z-index 0.3s 完全无效——你看到的永远是“跳变”,不是“滑动”。这不是写法问题,是 CSS 规范本身就不允许。
常见错误现象:给弹窗加 transition: all 0.3s,点击后 z-index 突然从 10 变成 9999,但没过渡;或者配合 opacity 或 transform 一起过渡时,遮挡关系却“啪”一下切换,造成视觉割裂。
- 真正能过渡的层叠相关属性只有
opacity和transform(间接影响渲染层) - 如果想模拟“层级渐进”,得靠
opacity+pointer-events配合控制交互时机 - 别在
@keyframes里动画z-index,同样无效,且部分浏览器会静默忽略整段规则
用 transform: translateZ() 替代 z-index 动画?小心触发新层
translateZ() 属于 transform,能被过渡,但它本质是让元素进入独立的 GPU 渲染层(layer),这会带来副作用:
- 可能意外提升元素层级,盖住本该在上面的其他
position: fixed元素(比如导航栏) - 频繁创建/销毁层会增加内存开销和重绘压力,尤其在低端设备上卡顿明显
-
translateZ(0)不等于“无效果”,它强制新建合成层,和原生z-index的 stacking context 逻辑不兼容
使用场景有限:只适合小范围、低频次、明确需要 3D 动画效果的组件(比如卡片翻转)。日常模态框、下拉菜单这类,别为“过渡感”硬套 translateZ。
立即学习“前端免费学习笔记(深入)”;
真正可靠的层级过渡方案:opacity + visibility + z-index 组合控制
要让“显示→遮挡→隐藏”有连贯感,得把动画拆开:视觉变化走 opacity,交互开关走 visibility,层级锚点用静态 z-index。
- 初始状态:
opacity: 0; visibility: hidden; z-index: 10; - 显示中:
opacity: 1; visibility: visible; z-index: 10;(z-index不变) - 关闭前先
opacity: 0过渡,等动画结束再设visibility: hidden(避免点击穿透) - 关键:所有参与遮挡关系的元素,
z-index必须预先设好且固定,不要在动画过程中修改
示例:一个下拉菜单打开时,背景蒙层和菜单本体共用同一组预设 z-index(如蒙层 z-index: 99,菜单 z-index: 100),只动 opacity 和 transform: translateY()。
Chrome DevTools 里怎么验证是否真有层叠问题?
别只看元素面板里的 z-index 值——它只是 stacking context 的局部参考。实际渲染顺序受父级 transform、opacity 、<code>will-change 等隐式触发条件影响更大。
- 打开 Chrome DevTools → More Tools → Layers,拖动时间轴看层是否意外分裂或合并
- 勾选 “Paint flashing”:闪烁区域越密集,说明合成层切换越频繁,
z-index相关动画越可能出问题 - 检查 computed 样式里的
stacking context字段,如果显示 “Yes”,说明该元素已脱离普通文档流层级,z-index行为会受限
最常被忽略的是:父容器加了 transform 或 opacity: 0.99,就足以让子元素的 z-index 失效——这种坑没法靠肉眼发现,必须进 Layers 面板确认。








