z-index无效的根本原因是未定位或被父级堆叠上下文隔离;需确认position非static,检查transform/opacity等触发上下文的属性,并调整父容器z-index或使用portal绕过。

z-index 设再大也盖不住,不是数值不够,而是它根本没进同一个“比大小”的场——要么元素压根没定位,要么被某个父级悄悄建的堆叠上下文锁死在局部范围里。
目标元素的 position 是不是 static?
这是最常卡住的第一步。z-index 对 position: static(默认值)完全无效,浏览器直接忽略整行声明。
- 打开 Chrome DevTools → 选中被遮挡元素 → «Computed» 面板搜索
position,确认计算值是relative、absolute、fixed或sticky - 临时加
position: relative(不位移、不影响布局),如果遮挡立刻消失,就坐实了这个问题 - flex / grid 子项虽未显式写
position,也能用z-index,但仅限该容器内部生效,且仍受祖先堆叠上下文限制 - 别给所有元素统一加
position: relative——可能意外创建堆叠上下文,或干扰 flex/grid 的自动对齐
哪个父级在偷偷创建堆叠上下文?
真正拦住你的不是数字小,而是某个父元素加了 transform、opacity、filter 等属性,无声建了个“玻璃罩”,子元素再高的 z-index 也出不去。
- 选中被遮挡元素 → «Layout» 标签页看
Stacking context是否为Yes;如果是,点右侧Show stacking context,它会高亮整个上下文边界 - 逐级点击父节点,在 «Computed» 里搜
transform、opacity、filter、will-change、isolation—— 任意一个非默认值,就是源头 -
overflow: hidden+ 非staticposition组合也会强制创建堆叠上下文,且还会裁剪子元素内容 -
transform: scale(1)、translateZ(0)、rotate(0)这些“看起来没变”的值,一样会截断层级链
该调谁的 z-index 才真正有效?
子元素的 z-index 再高也没用,它出不去父级上下文。真正要调的是那个“关住它”的父容器本身的 z-index 值,或者绕开它。
- 如果父容器加
transform只是为了过渡动画,且可删,直接移除比狂堆数字干净十倍 - 如果必须保留(如淡入/模糊),就给该父容器本身设
position: relative+ 合理z-index(比如z-index: 1050),而不是只给子元素设9999 - 对
modal、tooltip类组件,更彻底的解法是用 React Portal 或 Vue Teleport 把元素挂到下,绕开所有祖先上下文 -
z-index: 0和z-index: auto效果完全不同:0只要元素已定位,就会创建新上下文;auto不会
最易被忽略的一点:移动端 Safari 对 transform 和 opacity 极其敏感,opacity: 0.99 就足以触发新堆叠上下文。真机调试时,别只信桌面 Chrome 的表现。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











