z-index 失效的主因是元素未处于同一层叠上下文——父元素设置 opacity、transform、filter 等属性会创建新层叠上下文,使子元素 z-index 仅在该上下文中生效;需用开发者工具检查 stacking context 并调整元素层级或移除触发属性。

z-index 失效不是 CSS 写错了,而是元素没进入同一个层叠上下文(stacking context)——这是 90% 的真实原因。
为什么 z-index 设了却不起作用?
最常见的情况是:两个想比高低的元素,根本不在同一“楼层”里。CSS 的层叠不是全局排序,而是按层叠上下文分层管理。父元素一旦创建了新的层叠上下文(比如设置了 opacity: 0.99、transform: translateZ(0)、filter: blur(1px) 或 will-change: transform),它的子元素的 z-index 就只在这个“小楼”里生效,再大也盖不过隔壁“大楼”的一楼。
- 检查目标元素及其所有祖先,是否有触发新层叠上下文的属性(
opacity、transform、filter、will-change、isolation: isolate等) - 用浏览器开发者工具的“Computed”面板看该元素是否显示
stacking context: true - 特别注意:
position: static元素无视z-index,必须先设position(relative、absolute、fixed或sticky)
怎么确认两个元素在同一个层叠上下文里?
用开发者工具逐层展开 DOM,观察它们最近的共同父级是否已建立层叠上下文。如果中间某层有 transform: scale(1) 或 opacity: 0.999,那它就是“隔离墙”。
- 临时移除可疑父元素的
transform、opacity等属性,看z-index是否恢复生效 - 若不能删这些样式,就把需要置顶的元素“提级”——移到更高层级的容器中(比如挂到
下),绕过中间层叠上下文 - 避免对父容器滥用
will-change: transform,它会强制创建新层叠上下文,且无法被子元素的z-index跨越
z-index 数值设多大才够用?
数值本身没有上限,但盲目设 z-index: 9999 是掩盖问题。真正有效的是让元素处于可比较的上下文中。
- 同一层叠上下文内,
z-index值大的在上;未设置或设为auto的按 HTML 流顺序排布(后写的在上) - 负值合法(如
z-index: -1),但会让元素沉到其父容器背景之下(可能被遮挡) - 推荐用小整数区间管理:比如
z-index: 10(弹窗遮罩)、20(弹窗内容)、30(顶部提示条),避免无意义的超大数字
哪些“看似合理”的写法实际会破坏层叠关系?
这些操作常被忽略,却直接切断 z-index 的作用链:
-
position: relative+z-index: 1的父容器,会创建新层叠上下文 → 它的子元素再设z-index: 999也只在它内部有效 -
opacity: 0.99和opacity: 1效果几乎一样,但前者会创建新层叠上下文,后者不会 -
backface-visibility: hidden在某些旧版 Safari 中也会触发层叠上下文 - 使用
iframe时,其内部文档完全独立于外层层叠上下文,z-index无法跨 iframe 控制层级
真正难的不是调数字,而是看清当前 DOM 结构里到底建了几栋“楼”,以及你的元素在哪一层的哪一间房里。调试时优先查层叠上下文,而不是加 !important 或狂堆 z-index 值。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











