下拉菜单被模态框或导航栏遮挡是因 z-index 层级设计所致:dropdown-menu 默认 1000,modal 为 1050、navbar 固定定位常为 1030;需用更具体选择器(如 .navbar .dropdown-menu)覆盖 z-index 并确保父容器有定位,同时注意 transform 等触发层叠上下文的问题。
下拉菜单被模态框或导航栏遮挡
bootstrap 的 .dropdown-menu 默认 z-index 是 1000,而 .modal 是 1050、.navbar(固定定位时)常设为 1030,所以菜单一展开就被盖住。这不是 bug,是设计好的层级策略——但实际项目里经常得调。
最直接的办法是覆盖 CSS,但要注意作用域和加载顺序:
- 必须确保你的样式在 Bootstrap CSS 之后加载,否则会被覆盖
- 推荐用更具体的选择器,比如
.navbar .dropdown-menu或.modal .dropdown-menu,避免全局污染 - 别只改
z-index,顺手加上position: relative(如果父容器没定位,z-index 不生效)
示例(修复 navbar 内下拉被遮):
.navbar .dropdown-menu {
z-index: 1060;
}
自定义 dropdown-menu 的 z-index 值
Bootstrap 5+ 把 z-index 提到了 Sass 变量里,如果你用源码编译,改 $zindex-dropdown 最干净;但多数人用 CDN 或已编译 CSS,这时变量不生效,只能 CSS 覆盖。
关键点:
- Bootstrap 5.3 的默认值:
$zindex-dropdown: 1000,$zindex-sticky: 1020,$zindex-fixed: 1030,$zindex-modal: 1050 - 别设成 9999 这种魔数——后续加个 toast 或 tooltip(默认 1080)又得再调
- 如果项目用了多个第三方组件(如 datepicker、select2),它们的 z-index 可能互相打架,建议统一收口到一个
:root变量里管理
下拉菜单在 transform 容器里错位还遮不住
当 .dropdown 父元素有 transform、perspective 或 filter 时,会创建新的层叠上下文(stacking context),导致 z-index 相对它计算,而不是整个页面。这时候调 z-index 没用。
解决路径:
- 优先移除父级的
transform(比如把translateY改成top+position: relative) - 不行的话,在触发下拉的元素上加
style="transform: none !important;"(临时救急) - 或者把
.dropdown-menu用portal方式挂到<body>下(需 JS 配合,Bootstrap 5.2+ 原生支持boundary: 'window'选项)
JS 初始化示例(防止被 transform 容器截断):
new bootstrap.Dropdown(element, {
boundary: 'window'
});
为什么改了 z-index 还没用
常见真凶不是 z-index 值本身,而是层叠上下文被意外创建:
- 父元素有
opacity < 1、will-change、isolation: isolate,都会触发新层叠上下文 - 浏览器 DevTools 里看 computed 样式,搜
z-index,如果显示auto,说明该元素根本没参与层叠排序 - 移动端 Safari 对
transform+z-index组合尤其敏感,有时要加-webkit-transform: translateZ(0)强制提升
真正卡住的时候,先打开 Layers 面板(Chrome DevTools → Rendering → Enable paint flashing + Layers),看下拉菜单是不是被框在某个小的 layer 里——那基本就是层叠上下文惹的祸。
z-index 本身很简单,难的是它背后那一整套层叠上下文规则。改之前,先确认你是在跟哪个上下文较劲。


















