z-index失效主因是元素未定位或被父层叠上下文隔离;需确认position非static,并逐级检查opacity<1、transform非none等触发stacking context的祖先元素。

z-index 失效,99% 不是数值写小了,而是你正被某个父元素悄悄创建的层叠上下文(stacking context)卡住——子元素再高的 z-index 也出不去那个“盒子”。
检查目标元素是否已定位(position 不是 static)
浏览器压根不读 z-index,只要元素的 position 是 static(默认值)。这不是“效果弱”,是“不参与层叠计算”。
- 用 Chrome DevTools 的 «Computed» 面板搜
position,确认最终值不是static - JS 动态插入浮层(如 toast、picker)时,常漏掉
position声明,必须显式设position: fixed或position: absolute - Vue/React 中 class 切换后,可能被其他样式覆盖回
position: static,需检查最终 computed 值 - 临时加一句
position: relative(不影响文档流),立刻验证是否恢复层级控制
用 DevTools 定位哪个父级在创建“结界”(Stacking context: Yes)
只要某个祖先元素满足以下任一条件,它就创建了新的层叠上下文,子元素的 z-index 就只在它内部起作用:
-
opacity小于 1(哪怕opacity: 0.999) -
transform不为none(包括transform: translateZ(0)、scale(1)、rotate(0.0001deg)) -
filter不为none(哪怕filter: blur(0)或filter: opacity(1)) -
will-change: transform或will-change: opacity isolation: isolate-
position: fixed或sticky且z-index不是auto
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 在 Elements 面板中逐级点击父节点,右侧面板 «Layout» 标签页下盯紧 «Stacking context» 是否突然变成
Yes - 重点盯那些“没写
z-index却显示Yes”的节点——大概率是它用了transform或opacity - 临时注释掉可疑样式(比如
filter: blur(2px)),看遮挡是否立刻消失
警惕 z-index: 0 和 z-index: auto 的语义陷阱
很多人以为加个 z-index: 0 很安全,其实它会强制创建新层叠上下文;而 z-index: auto(默认)不会(前提是元素已定位)。
- 检查父容器是否意外设置了
position: relative+z-index: 0—— 这等于主动建了个结界 - 如果只是想让元素参与层叠排序但不想隔离上下文,用
z-index: auto更稳妥 -
z-index: -1会让元素沉到父上下文的背景和边框之下,慎用
修复思路:提级或绕开,而不是堆数字
两个不同堆叠上下文里的元素,即使子元素 z-index: 9999,也可能被父级 z-index: 1 的容器整体压在下面。
- 把需要“突围”的元素(如 dropdown、tooltip、modal)用
position: fixed挂到<body>下(记得手动处理滚动偏移) - 删掉父级不必要的
transform或opacity—— 如果视觉效果允许,这是最干净的解法 - 别只修子元素,要么删掉父级触发上下文的属性,要么提升整个容器的
z-index
真正难的不是写多大的 z-index,而是看清哪一层“结界”把你卡住了。iOS Safari 对 <html> 和 <body> 上的 transform、opacity 极其敏感,这类问题在移动端尤其容易被忽略。


















