z-index不生效的主因是父容器创建了层叠上下文,需优先检查最近定位祖先是否设置了z-index(含z-index:0),并调整其值而非仅调高子元素;同时确保元素有position属性且避免transform等隐式触发层叠上下文的属性。

z-index 不生效?先检查父容器是否创建了新的层叠上下文
Bootstrap 里写 z-index: 9999 却盖不住别人,大概率不是 z-index 数值不够,而是父元素悄悄“截断”了层级。比如 .modal、.dropdown、.navbar 这些组件内部都设置了 position: relative + z-index,它们会创建新的层叠上下文(stacking context),子元素的 z-index 只在这个上下文内比较,再大也超不出父容器的“天花板”。
常见错误现象:position: absolute 的提示框被 .card 或 .input-group 挡住,调试时发现它的 z-index 明明比父级高,但没用。
- 先用浏览器开发者工具检查目标元素的**最近定位祖先**(即最近的
position不为static的祖先) - 如果该祖先有
z-index(哪怕只是z-index: 0),它就已形成层叠上下文——此时你得调高它的z-index,而不是只调高子元素 - Bootstrap 5 的
$zindex-modal默认是1055,如果你的自定义弹窗要盖过 modal,父容器至少得设成z-index: 1056
Bootstrap 的 z-index 常量在哪查?别硬记,直接看 _variables.scss
Bootstrap 并不鼓励你随便写 z-index: 99999,它在源码里预定义了一套层级体系,比如 $zindex-dropdown、$zindex-sticky、$zindex-fixed。这些变量才是你该对齐的基准,否则容易和未来升级冲突。
使用场景:你要让一个自定义 tooltip 盖过 navbar 但低于 modal,就得查清楚它们的数值关系。
- Bootstrap 5.3 中关键值:
$zindex-dropdown: 1000,$zindex-sticky: 1020,$zindex-fixed: 1030,$zindex-modal-backdrop: 1040,$zindex-modal: 1055 - 这些变量在
node_modules/bootstrap/scss/_variables.scss里,修改前建议用 Sass 覆盖而非直接改 node_modules - 若用 CDN,可参考 Bootstrap 官方 CSS 中的注释,例如
/* stylelint-disable scss/dollar-variable-default */后面紧跟着的注释块
重叠元素定位失效?确保 position 属性已正确设置
z-index 只对定位元素生效(position 为 relative、absolute、fixed 或 sticky)。Bootstrap 的很多 class(如 .d-inline、.float-start)本身不触发定位,光加 z-index 是白搭。
常见错误现象:给一个 <div class="badge"> 加 <code>z-index: 10,结果还是被后面的文字压住。
- 必须显式加定位,例如:
class="badge position-relative z-3"(Bootstrap 5+ 提供z-0到z-3工具类) - 慎用
position: relative在行内元素上(如<span></span>),它可能撑开父容器高度;优先考虑position: absolute配合父容器position: relative - Bootstrap 5 的
.z-*工具类等价于z-index: *,但仅当元素已有定位属性时才起作用
移动端重叠错乱?注意 transform 触发的隐式层叠上下文
在 iOS Safari 或部分安卓 WebView 中,只要元素用了 transform(哪怕只是 transform: translateZ(0)),就会强制创建新层叠上下文——这会让原本设计好的 z-index 关系突然失效。
使用场景:你用 transform: scale(0.95) 做 hover 效果,结果 hover 后弹出的 tooltip 突然被压在下面。
- 检查是否无意中继承了
transform(比如父级用了.animate__animated或第三方动画库) - 避免对需要参与层级控制的容器使用
transform;如必须动画,改用top/left+transition替代 - 临时调试技巧:在开发者工具中禁用元素的
transform,看 z-index 是否立刻恢复正常
真正难的不是写多大的 z-index,而是搞清当前元素到底处在第几层“楼”里——每一层楼的“地面标高”由最近的定位祖先决定,而 transform、opacity、will-change 这些属性会偷偷给你盖新楼。调的时候别只盯着数字,先按住 Ctrl+Shift+C 看结构。











