z-index失效主因是祖先元素创建了堆叠上下文,而非数值过小;需确认元素已定位(非static)、检查触发堆叠上下文的属性(如opacity<1、transform等),并优先调整父容器z-index或移除冗余上下文。

z-index 失效几乎从不因为数值写小了,而是你没意识到某个祖先元素已经创建了新的堆叠上下文(stacking context),把目标元素“关”在里面比大小了——它再怎么调 z-index,也出不去。
为什么加了 z-index 还是被盖住?先看 position 生效没
最基础但最高频的错误:写了 z-index: 999,却忘了元素必须是已定位状态。position: static(默认值)下,z-index 完全被浏览器忽略,不报错、不警告。
- 用 Chrome DevTools 打开 Elements 面板 → 选中该元素 → 右侧 Computed 标签页里搜
position,确认不是static - 临时加一句
position: relative(不影响文档流),立刻验证是否恢复层级控制 - JS 动态插入或 Vue/React 中 class 切换后,容易漏掉
position声明;注意 CSS 优先级是否覆盖了它
父元素悄悄建了“结界”:哪些属性会触发堆叠上下文
只要某个祖先元素满足以下任一条件,它就创建了新的堆叠上下文,子元素的 z-index 只在它内部生效,无法和外部同级元素竞争:
-
opacity小于 1(哪怕opacity: 0.999) -
transform不为none(包括看似无害的transform: translateZ(0)、scale(1)、rotate(0.0001deg)) -
filter不为none(哪怕filter: blur(0)) -
will-change设为transform或opacity isolation: isolate-
position: fixed或sticky且z-index不是auto - Flex/Grid 容器中,子项设置了
z-index(非auto)
Chrome DevTools 的 Layout 标签页里,“Stacking context” 突然变成 Yes 的那个节点,就是“结界源头”。临时注释掉它的 transform 或 opacity,遮挡通常立刻消失。
立即学习“前端免费学习笔记(深入)”;
z-index: 0 和 z-index: auto 效果完全不同
很多人以为加个 z-index: 0 很安全,其实它会强制创建新堆叠上下文——而 z-index: auto(默认)不会(前提是元素已定位)。这个细节常导致“明明啥都没动,突然就盖不住了”。
- 检查父容器是否意外设置了
position: relative+z-index: 0,这等于主动建了个结界 - 如果只是想让元素参与层叠排序但不想隔离上下文,用
z-index: auto更稳妥 -
z-index: -1会让元素沉到父上下文的背景和边框之下,慎用
真正该改的是谁的 z-index?
子元素的 z-index 再高,也破不了父级的上下文边界。决定整个“小世界”在全局起始高度的,是父容器自身的 z-index。
- 如果父容器加
transform是为动画过渡,且可删,直接移除——比堆数字干净十倍 - 如果必须保留(如淡入/模糊效果),就把该父容器自身设为高
z-index,例如z-index: 1050 - 对
modal/tooltip类组件,更彻底的解法是用createPortal(React)或Teleport(Vue)挂到document.body下,完全脱离干扰上下文
真正难的不是改哪一行 CSS,而是意识到:z-index 不是独立变量,它是嵌套在层叠上下文树里的相对值。每次想加个 9999 前,先往上点三下 DevTools —— 那个突然标红的 Stacking context: Yes 才是你该修的地。


















