z-index失效主因是祖先元素创建了堆叠上下文,或目标元素position为static;需检查computed position、逐级排查stacking context、避免opacity/transform等隐式触发条件,并优先用createPortal脱离嵌套。

z-index 写了但没反应,大概率不是数值太小,而是某个祖先元素悄悄创建了堆叠上下文(stacking context),把你的元素“关”在里面比大小了——它根本出不去。
目标元素的 position 是不是 static?
z-index 只对 position 为 relative、absolute、fixed 或 sticky 的元素生效。默认 static 下,浏览器直接忽略 z-index,连计算都不做。
- 在 Chrome DevTools 的 «Computed» 面板里搜
position,确认最终值不是static - 临时加一行
position: relative(几乎不影响布局),看z-index是否立刻起效 - Vue/React 中动态插入样式时容易漏掉
position;用 class 切换时,也要防被其他规则覆盖回static
父级有没有偷偷建“结界”?
只要某个祖先元素满足以下任一条件,它就会创建独立堆叠上下文,子元素的 z-index 就只在它内部有效——哪怕你写 z-index: 9999,也跨不出去。
- 打开 Elements 面板,从目标元素开始逐级点击父节点,在右侧面板 «Layout» 标签页下看 «Stacking context» 是否突然变成 Yes
- 重点盯那些“没写
z-index却标为 Yes”的父元素:大概率是它用了opacity: 0.99、transform: translateZ(0)、filter: blur(0)或will-change: transform - 临时注释掉这些属性,观察遮挡是否消失——这是最快验证手段
为什么 z-index: 0 反而更危险?
z-index: 0 和 z-index: auto 效果完全不同:前者会显式创建新堆叠上下文,后者不会(前提是元素已定位)。很多人以为加个 0 很安全,结果它正是问题源头。
立即学习“前端免费学习笔记(深入)”;
- 检查父容器是否意外设置了
position: relative+z-index: 0—— 这等于主动建了个“结界” - 如果只是想让元素参与层叠排序但不想隔离上下文,用
z-index: auto更稳妥 -
z-index: -1会让元素沉到父上下文的背景和边框之下,慎用
怎么让元素真正“浮出来”?
别只调子元素的 z-index,修复动作得落在触发上下文的那个父容器上,或者干脆绕过它。
- 给那个触发堆叠上下文的父容器本身加
position: relative+ 合理的z-index(比如z-index: 100) - Modal、Tooltip 等浮层组件,优先用
createPortal挂到document.body下,彻底脱离嵌套干扰 - 避免对非必要容器设
z-index: 0:它会显式创建新上下文,而z-index: auto不会
最常被忽略的是:transform: scale(1)、opacity: 0.999、甚至 backdrop-filter: blur(0) 这些“看似无害”的值,都会静默建墙。问题不在你写的那行 z-index,而在 DOM 路径上某处,一个没声没息就截断层级链的 transform 或 opacity。


















