z-index失效主因是元素未定位或父元素创建了层叠上下文;需确保position非static,并检查opacity、transform、filter等是否触发新上下文,导致子元素z-index仅在内部生效。

z-index 不是开关,而是排序规则;它只在“同一间屋子”里管用——这间屋子叫层叠上下文。
为什么加了 z-index 还是被盖住
最常见的情况是:目标元素没定位,或被父级“关进小房间”。z-index 对 position: static 完全无效;而一旦父元素设置了 opacity: 0.99、transform: scale(1)、filter: blur(0.5px) 或 will-change: transform,就会创建新的层叠上下文——子元素的 z-index 只能跟兄弟比,出不了这个父容器。
检查方法:Chrome DevTools → Elements → Computed → 搜 stacking context。如果某祖先节点显示 “This element establishes a stacking context”,它就是遮挡源头。
- 临时删掉父级可疑样式(比如
opacity或transform),看遮挡是否消失 - 把目标元素剪切出来,直接挂到
<body>下测试,验证是否真由上下文导致 - 避免对非必要父容器设
will-change,它比transform更容易隐式创建层叠上下文
position 选 relative 还是 absolute?
选哪个取决于你是否想让它脱离文档流。position: relative 最安全:不改变布局位置,但能激活 z-index;position: absolute 适合完全脱离流的浮层(如弹窗、提示框),但必须确保其最近的已定位祖先能提供合理参照。
立即学习“前端免费学习笔记(深入)”;
- 只要是为了控制层级,优先加
position: relative——它不扰动布局,又解锁z-index - 用
absolute时,注意父容器若设了overflow: hidden、auto或scroll,会直接裁剪子元素,z-index根本没机会起作用 - 不要依赖“文档流顺序”来赌谁在上,后写的
static元素可能盖住前写的absolute元素,这是不可控的 fallback 行为
数值怎么设才不踩坑
z-index 不是越大越好,而是要分组管理。全局乱用 9999 会导致后续组件(比如模态框、下拉菜单)无法插入中间层级。
- 按功能划分区间:例如
--z-header: 100、--z-dropdown: 200、--z-modal: 1000、--z-toast: 1100 - 负值合法,但需配合
overflow: visible父容器,否则会被裁掉 -
z-index: auto和z-index: 0效果不同:auto不参与层叠排序,0明确进入当前上下文的“默认层”
调试时该看什么
别只盯着自己写的 z-index 值。打开 Chrome 的 Layers 面板(More Tools → Layers),能看到实际渲染的层叠结构。被遮挡的元素如果出现在底层面板里,说明它确实被锁死在某个父级上下文中,而不是数值不够大。
- 右键元素 →
Reveal in Layers panel,直观看到它属于哪一层 - 检查 computed styles 中
position是否仍是static,z-index是否计算为auto - DOM 结构层级和 CSS 层叠上下文层级不是一回事——有时挪动一个父容器的位置,比调十次
z-index更有效
真正卡住人的从来不是 z-index 写多少,而是没意识到:你写的那个数字,根本没被放进同一个比较池里。


















