z-index不生效的首要原因是元素未定位(position仍为static),必须设为relative/absolute/fixed/sticky才激活;其次,父级若触发层叠上下文(如opacity

z-index不生效,先看元素有没有定位
写了z-index: 999却没用?大概率是position还是static——这是最常被忽略的硬性前提。浏览器直接无视z-index声明,元素照旧按 DOM 顺序渲染。
检查方式:DevTools →「Computed」面板搜索position,确认值不是static;再搜z-index,看是否显示为具体数字(而非auto)。
- Flex/Grid 子项即使视觉上“浮动”,也必须显式加
position: relative才能启用z-index - Vue/React 中动态插入的按钮,JS 注入样式后可能覆盖了你写的
position,需检查最终生效样式 - 常见误操作:
.btn { z-index: 10; }→ 漏掉position: relative,完全无效
被遮挡不是数值小,而是层叠上下文断了
两个元素z-index分别是 999 和 1,但 1 的还是盖在上面?说明它们根本不在同一个“比较场”里——父容器悄悄创建了新的层叠上下文,把子元素锁死在局部。
触发新层叠上下文的属性包括:opacity小于 1(哪怕opacity: 0.99)、transform非none(含translateZ(0))、filter、will-change、isolation: isolate,以及position + z-index组合(哪怕z-index: 0)。
- DevTools → 选中目标元素 →「Computed」面板搜
stacking context,标为“Yes”就确认被隔离 - 逐级向上点开父节点,重点查
opacity、transform、filter是否意外存在 - iOS Safari 对
transform和will-change极其敏感,真机测试才可靠,模拟器常漏问题
Tailwind 中 z-xxx 类不生效的配置陷阱
配了z-999却没生成 CSS?Tailwind v3+ 已废弃数组写法,且extend.zIndex不生效——必须完整定义theme.zIndex对象。
正确写法示例:
module.exports = {
theme: {
zIndex: {
'background': '0',
'modal-overlay': '60',
'modal-content': '70',
'tooltip': '40',
'toast': '50',
}
}
}
- 键名必须是字符串(
'modal-overlay'),不能写modal-overlay或数字60 - 改完配置必须重启开发服务器,Tailwind 不热重载
-
z-[999]在 React 动态 class(如class={`z-[${depth}]`})中不会被 JIT 扫描到,生产环境必漏
父容器没设 z-index,子元素再高也出不去
子元素z-index: 100被兄弟容器里的z-index: 10盖住?不是子元素不够高,而是它所在的父容器层级太低——子元素的“高度”永远受限于父容器的层叠上下文边界。
典型场景:轮播图卡片用了transform: scale(0.99),里面弹出的按钮再调z-index也没用;或者两个弹窗分属不同父模块,谁在上取决于这两个父容器自身的z-index比较结果。
- 需要全局分层的组件(如弹窗、下拉菜单),应确保其最近共同祖先不提前创建层叠上下文
- 避免只给子元素加
z-index,而忽略父容器的定位与层级设置 - iframe 是独立文档环境,它的
z-index与父页面完全无关,无法通过 CSS 调整
z-index写错了数字,而是某一层父容器默默加了opacity: 0.99或will-change: transform,既不报错也不高亮,却把整个子树的层级逻辑锁死在局部。别急着堆数值,先用 DevTools 查 stacking context。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











