Tailwind的z-*类失效根本原因是元素未定位或父级触发层叠上下文:position为static时z-index被浏览器忽略;父元素含opacity<1、transform非none等属性会创建独立层叠上下文,使子元素z-index仅在局部生效。

Tailwind 的 z-* 类没效果,基本就两个原因:元素没定位,或者被父级“关进小房间”了——也就是触发了层叠上下文(stacking context)。
position 是 static,z-index 直接被浏览器忽略
Tailwind 的 z-50、z-modal-overlay 这些类,只对 position 为 relative、absolute、fixed 或 sticky 的元素生效。默认的 static 下,浏览器连解析都跳过,不是“压不住”,是“根本不参与”。
- 常见现象:给一个普通
<div>加z-50,毫无反应 - Flex/Grid 容器里的子项不会继承定位能力,每个需要层级控制的子元素都得自己加
relative或absolute - 动态插入的弹窗(如 toast)必须同步设置
position: fixed,不能只靠 JS 改z-*类 - 验证方法:打开 Chrome DevTools → Computed 面板 → 搜
position,确认值不是static;临时加relative看是否立刻生效
父元素悄悄创建了 stacking context,z-index 被锁死在局部
只要某个祖先元素满足以下任一条件,它就变成“结界入口”,所有后代的 z-index 只能在它内部比大小,无法和外部兄弟竞争:
-
opacity小于 1(哪怕opacity-95或opacity-99) -
transform不为none(scale-100、translate-z-0、rotate-0全部算) -
filter不为none(blur-sm、backdrop-blur-md都会触发) -
will-change: transform或isolation: isolate
调试建议:在 DevTools Elements 面板逐级点击父节点,右侧面板 Layout 标签页里看「Stacking Context」是否标为 Yes;临时删掉可疑父级的 opacity-95 或 scale-95,遮挡消失即确认。
立即学习“前端免费学习笔记(深入)”;
tailwind.config.js 里配置了但没生效
改完 theme.zIndex 却没生成对应 CSS,大概率踩中这些硬坑:
- 写在
extend.zIndex里 → Tailwind v3+ 不识别,等于白写 - 用数组语法:
zIndex: ['0', '50', '999']→ 已废弃,规则根本不会生成 - 键名没加引号:
50: '50'→ JS 解析成数字键,构建时可能丢失或顺序错乱 - 改完没重启 dev server → JIT 模式不热重载配置变更
✅ 正确写法必须是:theme: { zIndex: { 'modal-overlay': '60', 'tooltip': '40' } },且重启服务。
z-[999] 和动态拼接 class 在生产环境失效
React 中写 class={`z-[${depth}]`},或随意用 z-[2147483647],看似灵活,实则危险:
- JIT 引擎只扫描
content配置里出现的字面量字符串,动态拼接无法被静态分析 → 生产构建漏生成 - 第三方库(如 Headless UI)注入的 CSS 可能晚于你的 Tailwind 输出,导致
z-[999]被覆盖 - 没有语义,查问题时完全不知道
z-[999]对应哪个 UI 层级,协作成本飙升
真正难的不是堆数字,而是看清谁在哪个盒子里比大小——每次调 z-* 前,先确认它有没有被 position 拉进来,再确认它是不是被某个看不见的 opacity 或 transform 关进了独立空间。


















