z-index失效主因是祖先元素创建了新的堆叠上下文,使子元素z-index仅在该上下文内生效;opacity

z-index 失效不是值太小,是进了“结界”
绝大多数 z-index 看似写了却没用,根本原因不是 z-index: 9999 不够大,而是目标元素的某个祖先(不一定是直接父级)创建了新的堆叠上下文(stacking context),把它“关”在里面了。子元素的 z-index 只能在该上下文内比大小,跨不出去——就像在玻璃罩里争第一,罩子本身层级低,整个罩子还是被压在下面。
哪些 CSS 属性会悄悄建“结界”
这些样式看着无害,但只要出现,就会让该元素变成新层叠根:
-
opacity小于 1(哪怕opacity: 0.999) -
transform不为none(包括transform: translateZ(0)、transform: scale(1)) -
filter不为none(哪怕filter: blur(0)) -
will-change: transform或will-change: opacity isolation: isolate-
position: fixed或position: sticky且z-index不是auto - flex/grid 容器中,子项设置了
z-index(非auto)
特别注意:z-index: 0 和 z-index: auto 效果不同——前者会触发新上下文,后者不会(前提是元素已定位)。别以为加个 0 很安全,它可能正是问题源头。
怎么快速定位“结界”在哪
用 Chrome DevTools 直接查最准:
- 选中被遮挡的元素 → 右侧 «Computed» 面板 → 拉到底看
z-index是否灰显或标为(not applicable) - 逐级点击向上父节点 → 右侧 «Layout» 标签页里留意 «Stacking context» 是否突然变成
Yes - 打开 «Rendering» 面板 → 勾选 «Show layers panel» → 在 «Layers» 面板里直接看到每个上下文节点,点一下就能高亮对应 DOM 元素
- 临时注释掉疑似父级的
transform、opacity、filter,看遮挡是否消失——这是最快验证手段
重建上下文的两种务实路径
不能只修子元素,得看结构能不能动:
- 如果父容器加
transform或opacity只是为了过渡动画或兼容,且非必须,直接删掉——最干净 - 如果必须保留(比如淡入/模糊效果),就把需要“突围”的元素(如
tooltip、dropdown)用position: fixed+z-index提出来,挂到body下(注意处理top/left和滚动偏移) - 若多个模块共用一个父容器且都需高优先级显示,不如把该父容器自身设为高
z-index,让它整体“抬高”——比在内部疯狂堆z-index更可控、更可维护
真正麻烦的从来不是数字写多大,而是你不知道那个 transform: translateZ(0) 正躺在第 5 层祖先上,安静地封印了所有子元素的层级自由。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











