用offcanvas实现侧边展开+遮罩是唯一可靠路径:它天然支持transform推入、自动遮罩、ESC关闭、点击遮罩收起;必须挂载在body下,用offcanvas-start/end类控制方向,禁用遮罩需data-bs-backdrop="false"。
用 offcanvas 实现侧边展开 + 遮罩是唯一可靠路径
bootstrap 5 官方不提供“侧边展开遮罩菜单”这种独立组件,offcanvas 就是为此设计的标准方案——它天然包含 transform 推入、背景遮罩(backdrop)、键盘关闭(esc)、点击遮罩收起等全部行为。别写 position: fixed + 手动控制 display 或 visibility,那样遮罩层要自己算 z-index、监听点击、处理 esc、适配移动端滚动穿透,90% 的失败都源于绕开 offcanvas。
-
offcanvas默认启用 backdrop,无需额外配置;如需禁用,加data-bs-backdrop="false" - 遮罩层由 Bootstrap 自动插入 DOM,class 是
offcanvas-backdrop,不能手动写- 遮罩点击收起逻辑已内置,但前提是:触发按钮必须有
data-bs-toggle="offcanvas",且容器有正确id- iOS Safari 下遮罩可能失效?检查是否在
show.bs.offcanvas事件中错误设置了document.body.style.overflow = 'hidden'—— offcanvas 已自动处理,重复设置会冲突placement="end" 和 placement="start" 别写错
侧边展开方向由
offcanvas-end或offcanvas-start类决定,不是靠 CSS 的left/right调整。写错会导致菜单从顶部或底部滑出,或完全不可见。- 右侧展开:用
class="offcanvas offcanvas-end",对应按钮的data-bs-target="#sidebar"指向同 id 容器 - 左侧展开:用
class="offcanvas offcanvas-start",不要写成offcanvas-left(无效类) - 宽度定制必须用
style="--bs-offcanvas-width: 280px;",改width或max-width会破坏 transform 定位 - 移动端小屏下想默认隐藏?别加
d-none——offcanvas默认就是隐藏状态,只在触发时渲染
遮罩层被遮挡?z-index 和父容器 overflow 是关键
遮罩层显示但菜单没出来,或者菜单出来了但遮罩没覆盖全屏,大概率是 z-index 冲突或父容器截断了渲染流。
-
offcanvas-backdrop默认z-index: 1050,菜单容器默认z-index: 1045;若页面已有 navbar(z-index: 1040)或 footer,遮罩不会被盖住,但若你手动设了更高 z-index(如 2000),遮罩就失效了 - 外层容器(比如
.container-fluid或.row)设了overflow: hidden或transform,offcanvas 的transform动画会被裁剪 —— 清掉这些样式,或把 offcanvas 移到直接子级 - 遮罩只覆盖视口,不覆盖 fixed 定位的元素(如顶部导航栏)——这是正常行为,不是 bug;若需遮住 navbar,得手动调高其 z-index 并确保它不带
overflow: hidden
移动端滚动穿透和键盘支持容易漏
用户在 offcanvas 展开后还能滚动背后页面,或按 ESC 不关闭,基本都是事件绑定或属性缺失导致。
- iOS Safari 滚动穿透:offcanvas 会自动在
show.bs.offcanvas中设body.style.overflow = 'hidden',但如果你在其他地方(比如自定义 modal)也操作了overflow,没恢复就会残留;监听hidden.bs.offcanvas事件,在里面重置body.style.overflow = '' - 键盘关闭失效:确认关闭按钮是
,不是手写的×或onclick="myClose()"—— 后者不响应 ESC - 焦点管理出问题?确保 offcanvas 容器有
tabindex="-1",且首次展开后焦点自动落到第一个可聚焦元素(如第一个);若没发生,检查内部是否所有交互元素都带tabindex="0"或原生可聚焦
真正麻烦的不是怎么让菜单滑出来,而是让它在各种设备上不卡顿、不漏点、不读错、不挡住关键操作——offcanvas 的每个细节(backdrop、tabindex、transform、z-index)都是为这些场景打磨过的,跳过它等于重造轮子。
- 遮罩点击收起逻辑已内置,但前提是:触发按钮必须有











