z-index失效的根本原因是元素未定位或被父级堆叠上下文限制;需先确认position非static,再逐级排查opacity、transform、filter等隐式创建堆叠上下文的属性。

z-index设再大也盖不住,根本不是数值问题,而是元素没定位或被父级堆叠上下文“锁死”在局部范围里;必须先确认position值有效,再逐级排查opacity、transform、filter等隐式创建堆叠上下文的属性。
检查目标元素是否已定位(position非static)
z-index对position: static(默认值)完全无效,哪怕写z-index: 9999,浏览器也会直接忽略。打开 Chrome DevTools → 选中被遮挡元素 → «Computed» 面板搜索position,看实际计算值是不是relative、absolute、fixed或sticky。
- 临时加
position: relative(不位移,不影响布局),遮挡立刻消失?说明就是这一步卡住了 - flex 或 grid 子项虽未显式写
position,也能用z-index,但仅限该容器内部生效,且仍受祖先堆叠上下文限制 - 别给所有元素统一加
position: relative——可能意外创建堆叠上下文,或干扰 flex/grid 的自动对齐行为
用 DevTools 快速定位哪个父级在创建堆叠上下文
真正拦住你的不是数值不够,而是某个父元素悄悄建了个“玻璃罩”。选中被遮挡元素 → «Layout» 标签页查看Stacking context是否为Yes;如果是,点右侧Show stacking context,它会高亮整个上下文边界(通常是一个父<div>)。
- 逐级点击那个父节点,在 «Computed» 里搜
transform、opacity、filter、will-change、isolation—— 任意一个非默认值,就是源头 -
overflow: hidden、auto或scroll+ 非staticposition组合时,也会强制创建堆叠上下文,且还会裁剪子元素内容 - 特别注意:
z-index: 0和z-index: auto效果完全不同:前者只要元素已定位,就会创建新上下文;后者不会
修复时调谁的z-index才真正有效
子元素的z-index再高也没用,它出不去父级上下文。真正要调的是那个“关住它”的父容器本身的z-index值,或者干脆绕开它。
立即学习“前端免费学习笔记(深入)”;
- 如果父容器加
transform只是为了过渡动画,且可删,直接移除比狂堆数字干净十倍 - 如果必须保留(如淡入/模糊),就给该父容器本身设
position: relative+ 合理z-index(比如z-index: 1050),而不是只给子元素设9999 - 对
modal、tooltip类组件,更彻底的解法是用 React Portal 或 Vue Teleport 把元素挂到<body>下,绕开所有祖先上下文
复杂点在于:同一个页面里可能嵌套多层堆叠上下文,而 DevTools 的 «Layers» 面板只能显示最外层分组,内层需手动逐级点开验证;最容易被忽略的是opacity: 0.999或transform: scale(1)这种“看起来没变”的属性,它们一样会截断层级链。


















