bootstrap 5 三级菜单无法靠 data-bs-toggle="dropdown" 自动生效,因其官方彻底移除了对嵌套 dropdown-menu 的 js 支持;子级无实例、不响应事件,必须用 js 主导方案手动控制 show/hide、阻止冒泡、重置 popper,并配合响应式降级与 aria 无障碍支持。

Bootstrap 5 的三级菜单根本不能靠 data-bs-toggle="dropdown" 自动生效
不是你 HTML 写错了,是 Bootstrap 5 官方彻底移除了对嵌套 dropdown-menu 的 JS 支持。哪怕你写成 <div class="dropdown-menu"><div class="dropdown-menu"><div class="dropdown-menu">,第三级也始终 <code>display: none,且 mouseenter、click、Tab 都不会触发它——因为 bootstrap.Dropdown 实例只初始化第一层带 data-bs-toggle="dropdown" 的元素,子级压根没被接管。
纯 CSS 悬停方案只适用于桌面,且必须修复三个定位硬伤
如果你只需要鼠标悬停展开、不关心触屏和键盘导航,可以用 CSS 强制显隐,但必须同时处理:
-
.dropdown-item必须加position: relative,否则子级.dropdown-menu的left: 100%会相对于 body 定位,直接飞出视口 -
.dropdown-menu .dropdown-menu要显式设为position: absolute; top: 0; left: 100%; display: none;,不能依赖默认样式 - 必须覆盖 Bootstrap 5 默认加在嵌套菜单上的
opacity: 0和visibility: hidden,否则display: block会被压制
关键 CSS 片段:
.dropdown-item { position: relative; }
.dropdown-menu .dropdown-menu {
position: absolute;
top: 0;
left: 100%;
display: none;
}
.dropdown-item:hover > .dropdown-menu,
.dropdown-item:focus > .dropdown-menu {
display: block;
}
JS 主导方案要手动管理 show/hide + 阻止冒泡 + 重置 Popper
真正可用的三级菜单必须用 JS 控制,否则移动端一点就收、键盘无法进入、屏幕阅读器报错。核心动作不是“加更多 class”,而是干预三件事:
- 给二级触发项(如“产品”)加自定义类
dropdown-submenu-toggle,而不是再套data-bs-toggle="dropdown" - 三级菜单容器必须是独立节点(比如
<div id="submenu-products" class="dropdown-menu dropdown-submenu">),初始 <code>display: none - 监听
click时调用e.stopPropagation(),否则点击二级项会触发一级菜单关闭 - 二级菜单需加
data-bs-popper="none",避免 Popper 把三级菜单重定位到奇怪位置 - 三级菜单自身加
position-static,防止被 Popper 的transform错位
响应式降级和无障碍支持最容易被跳过
小屏下硬塞横向三级菜单必然溢出或被裁剪,dropend 类对二级及以上完全无效。必须用 @media (max-width: 992px) 手动把三级菜单改为垂直展开:top: 100%; left: 0;。更关键的是 ARIA 属性:手动切换 aria-expanded="true/false" 和 aria-haspopup="menu",否则屏幕阅读器根本不知道这里有子菜单。键盘导航还得监听 ArrowRight/ArrowLeft 并手动聚焦,纯 CSS 方案对此完全无解。











