z-index无效主因是元素未定位或被父级层叠上下文隔离:position为static时浏览器完全忽略z-index;若祖先元素设置了opacity

z-index 设了却没用,不是值太小,而是它根本没资格参与全局层叠比较——要么元素没定位,要么被父级层叠上下文“锁死”在局部范围里。
元素没加 position 属性
z-index 只对 position 为 relative、absolute、fixed 或 sticky 的元素生效。position: static(默认值)下写 z-index: 9999 完全被忽略。
- 打开 DevTools,检查目标元素的
Computed样式,确认position不是static - 最小验证:临时加
position: relative,不改变布局,但能立刻激活z-index - 在 Vue/React 中动态加 class 时,容易漏掉配套的定位声明,要成对出现
父级创建了新的层叠上下文
只要某个祖先元素满足以下任一条件,就会建立独立的层叠上下文(stacking context),子元素的 z-index 就只能在它内部比大小,出不去。
-
opacity小于 1(哪怕opacity: 0.999) -
transform不为none(包括transform: translateZ(0)、scale(1)) -
filter不为none(哪怕filter: blur(0)) -
will-change: transform或will-change: opacity isolation: isolate-
position: fixed或sticky且z-index不是auto
常见踩坑点:z-index: 0 和 z-index: auto 行为不同——前者会创建新上下文,后者不会(前提是已定位)。
怎么快速定位是哪个父级在“截胡”
Chrome DevTools 提供了直接线索:
- 选中被遮挡的元素 → 右侧面板
Computed标签页 → 搜索stacking context - 如果某祖先节点显示
This element establishes a stacking context,它就是源头 - 更直观:打开
Rendering面板 → 勾选Show layers panel→ 切换到Layers标签页,点击就能高亮对应 DOM 节点 - 临时删掉疑似父级的
opacity、transform、filter,看遮挡是否立刻消失 - 把目标元素剪切出来,挂到
下测试——如果此时正常显示,基本坐实是层叠上下文问题
overflow: hidden 把元素直接裁掉了
这和 z-index 无关,但常被混淆。父容器设了 overflow: hidden(或 auto、scroll),会直接裁剪脱离文档流的子元素——绘制阶段就切掉了,层叠顺序根本没机会算。
- 检查父容器是否真需要
overflow: hidden;如果只是为了清除浮动,改用display: flow-root更安全 - 若必须保留
overflow,把定位元素移出该父容器 DOM,挂到更高层级(比如document.body),再用 JS 动态计算位置 -
overflow: clip(Chrome 119+)不解决层叠问题,也不能替代z-index的语义
真正难搞的从来不是数字写多大,而是那个 transform: translateZ(0) 躺在第 5 层祖先上,安静地封印了所有子元素的层级自由。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











