bootstrap 5 原生不支持多级下拉菜单,二级菜单需手动通过 css(桌面端 hover)或 js(移动端点击+键盘支持)实现,并严格处理定位、z-index、事件冒泡及 aria 属性同步。

Bootstrap 5 原生不支持多级下拉菜单,dropdown-menu 嵌套在另一个 dropdown-menu 内时,二级及以后的菜单默认不会显示、无法 hover 或 click 触发——这不是你代码写错了,是框架主动移除的功能。
为什么 .dropdown-item:hover .dropdown-menu 不生效
常见现象:鼠标悬停,二级菜单完全不出现,或一闪而过。根本原因不是 CSS 没写,而是结构和定位没对齐:
-
.dropdown-item缺少position: relative,导致子级.dropdown-menu的left: 100%相对于 body 定位,直接飞出视口 - HTML 中二级
.dropdown-menu不是.dropdown-item的**直接子元素**(比如被<div> 包了一层),CSS 选择器就断了 <li>Bootstrap 自带的 <code>.dropdown.show > .dropdown-menu规则会覆盖你的display: block,需用更高优先级或!important(仅调试用) - 没处理移动端:iOS/Android 上
:hover只在模拟悬停时短暂触发,纯 CSS 方案在手机上基本不可用 - 给带子菜单的
.dropdown-item加position: relative - 二级
.dropdown-menu设position: absolute; top: 0; left: 100%; margin-top: -2px; - 显隐规则用
.dropdown-item:hover > .dropdown-menu(注意>,确保是直接子元素) - 加
z-index: 1001(父级.navbar是 1000,至少高 1) - 禁用移动端 hover:用
@media (max-width: 991.98px)把 hover 规则包裹起来,避免小屏误触发 - 悬停断连:鼠标从二级移到三级时,哪怕加了
margin-left: -4px,微小间隙也会触发mouseleave,导致整个菜单收起 - 定位失控:
left: 100%套两层后,三级菜单位置严重偏移,且z-index需逐层递增(1001→1002→1003),CSS 无法动态管理 - JS 不识别:Bootstrap 的
Dropdown插件只初始化一级data-bs-toggle="dropdown",子级没实例,show类不会自动加到三级菜单上 - 正确做法是结构扁平化:把三级菜单抽离为独立
<div id="submenu-xxx" class="dropdown-menu dropdown-submenu">,用 JS 手动 <code>toggle('show')并管理aria-expanded移动端点击展开时菜单立刻关闭?关键在阻止事件冒泡
点击二级菜单项后,整个一级下拉立即收起,是因为 Bootstrap 默认监听了
click并触发关闭链。解决方法很明确:- 给二级触发项加
class="dropdown-submenu-toggle"和data-submenu-id="xxx" - JS 中监听该 class 的
click,调用e.stopPropagation()阻止事件冒泡到一级菜单 - 再手动控制对应三级菜单的
show类和aria-expanded属性 - 别忘了键盘导航:监听
Enter和Space键,行为要和 click 一致
最易被忽略的是:所有嵌套层级的
aria-haspopup、aria-expanded、aria-controls必须手动同步更新,否则屏幕阅读器用户完全无法感知菜单状态变化。 - 给二级触发项加
怎么用 CSS 实现稳定的二级菜单(桌面端)
只靠 CSS 能搞定桌面端 hover 展开,但必须严格满足以下条件:
三级菜单必须用 JS 控制,不能只靠 CSS
纯 CSS 实现三级菜单几乎必然失败,主要卡在三个地方:











