z-index不生效主因是元素未定位(position为static)或被父级层叠上下文隔离;需先确认position非static,再逐级排查opacity

z-index 不生效,99% 是因为元素根本没参与层叠计算,或者被父级“关进盒子”里了——不是数值写小了,而是层级关系断了。
检查目标元素的 position 是否为 static
浏览器对 position: static(默认值)完全忽略 z-index,连解析都不做。你写 z-index: 9999 和 z-index: 0 效果一样。
- 打开 Chrome DevTools,选中元素,在 «Computed» 面板搜
position,确认最终值不是static - 临时加一行
position: relative(不影响布局),刷新看遮挡是否立刻消失 - JS 动态插入弹窗/Tooltip 时,只设
z-index、漏掉position: fixed或position: absolute是高频错误 - Vue/React 中 class 切换后,样式可能被重置为
position: static或unset,得查最终 computed 值
逐级排查父级是否创建了层叠上下文(stacking context)
只要某个祖先元素满足以下任一条件,它就形成一个独立“结界”,子元素的 z-index 只能在内部比大小,出不去:
-
opacity小于 1(哪怕opacity: 0.999) -
transform不为none(包括transform: translateZ(0)、scale(1)、rotate(0.0001deg)) -
filter不为none(哪怕filter: blur(0)) -
will-change: transform或will-change: opacity isolation: isolate-
position: fixed或sticky且z-index不是auto
实操建议:在 Elements 面板逐级点击父节点,右侧面板 «Layout» 标签页盯紧 «Stacking context» 是否突然变成 Yes;重点查那些“没写 z-index 却显示 Yes”的节点——大概率用了 transform 或 opacity。
响应式断点中 z-index 突然失效的典型诱因
媒体查询里激活的 transform、opacity 或 filter 会静默创建新层叠上下文,尤其在移动端更敏感。
- 切到对应断点,用 «Computed» 面板搜
transform,看是否从none变成了具体值 - Flex/Grid 容器在断点中启用后,若同时带
opacity: 0.99,整个子项组就被隔离——别依赖“flex 子项自动有层级” - 媒体查询中改了
position(比如从static切到fixed),但漏掉同步加z-index,结果浮起来了却盖不住其他元素 -
z-index: 0在已定位元素上会强制创建新层叠上下文,而z-index: auto不会;误用前者等于主动建了个“结界”
修复思路:优先动容器,而非堆数值
两个不同层叠上下文里的元素,子元素再高的 z-index 也赢不过父容器整体层级低。盲目写 z-index: 9999 只会让后续维护越来越难。
- 删掉父级不必要的
transform或opacity(如果视觉允许) - 把需要“突围”的元素(如弹窗、下拉菜单)用 JS 移到
document.body下,配合position: fixed手动定位(注意滚动偏移) - 提升父容器自身的
z-index,而不是只调子元素——这才是治本 - 警惕
z-index: -1:它会让元素沉到父上下文的背景和边框之下,响应式切换中容易“突然消失”
真正难的不是算清哪个数字够大,而是每次改完样式,都得多往上翻两层 DOM,确认那个刚被激活的 transform 或 opacity 没把你关键元素锁死在盒子里。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











