z-index在不同层叠上下文中失效,根本原因是元素被隔离在独立“世界”内无法跨上下文比较;需通过DevTools定位首个Stacking context: Yes的祖先(如opacity<1、transform不为none等触发的“结界源头”),并删除该父级干扰属性或提升其z-index,而非盲目增大子元素z-index值。

z-index 在不同层叠上下文里失效,不是数值写小了,而是你试图让两个“不在同一个世界”的元素直接比高低——浏览器根本不允许跨上下文比较。
为什么 z-index 写了却像没写一样
最常见现象:z-index: 9999 的 tooltip 总被 z-index: 10 的 header 盖住。原因不是 tooltip 数值小,而是它的父容器(比如带 opacity: 0.99 或 transform: translateZ(0) 的卡片)已创建新堆叠上下文,tooltip 的 z-index 只在该卡片内部生效。
- 用 Chrome DevTools 选中 tooltip → «Computed» 面板查
z-index,若显示为 (not applicable) 或灰显,说明它根本没参与层叠计算 - 再点父节点 → «Layout» 标签页看 «Stacking context» 是否为 Yes;第一个标为 Yes 的就是“结界源头”
- 临时注释掉父级的
transform、opacity或filter,遮挡立刻消失——这就是实锤
哪些属性会静默创建堆叠上下文
这些样式看着无害,但只要偏离默认值,就强制生成独立层级空间:
-
opacity小于 1(哪怕opacity: 0.999) -
transform不为none(包括transform: scale(1)、translateZ(0)、rotate(0.0001deg)) -
filter不为none(哪怕filter: blur(0)或filter: opacity(1)) -
will-change: transform或will-change: opacity isolation: isolate-
position: fixed或sticky且z-index不是auto -
z-index: 0(注意:它会创建新上下文,而z-index: auto不会)
修复的关键不是堆数字,而是提级或绕开
子元素再怎么调 z-index,也破不了父级的“结界”。必须从结构层面解决:
立即学习“前端免费学习笔记(深入)”;
- 如果父容器的
transform或opacity非必需(比如只为触发硬件加速),直接删掉——最干净 - 如果必须保留(如淡入动画),就把需要浮出的元素(如
dropdown、modal)用 JS 移到document.body下,配合position: fixed手动定位(别忘了监听scroll和resize更新位置) - 更可控的做法:给那个触发上下文的父容器自身设高
z-index(比如z-index: 105),让它整体抬高,而不是在内部疯狂堆z-index: 9999
Tailwind 用户注意 zIndex 配置陷阱
zIndex 必须在 tailwind.config.js 中以对象语法定义(如 { 'modal': '60' }),改完要重启 dev server;z-[999] 动态拼接在构建时不会被扫描。
- 常见错误:
extend: { zIndex: { 'modal': '50' } }——theme.zIndex默认为空,追加无效 - 写成
modal: 50(数字)或modal(未加引号),JS 解析失败或截断 - 改完配置后没重启开发服务器——Tailwind 不热重载配置变更
真正难的不是算清哪个父级该设多少 z-index,而是每次加 transform 或 opacity 时,都要多看两层 DOM,确认没把关键浮层关进一个看不见的盒子里。


















