offcanvas 是模态式抽屉而非侧边栏,必须挂载在 下,否则遮罩失效、esc 无法关闭;需确保 data-bs-target 与 id 严格匹配,offcanvas-body 需设 max-height 和 overflow-y: auto,方向类不可混用或动态切换。

Offcanvas 不是侧边栏布局组件,而是模态式抽屉 —— 想用它做桌面端固定侧边栏,会踩坑;想在移动端做菜单或筛选面板,它开箱即用。
Offcanvas 必须挂载在 下,否则点击遮罩不关闭、ESC 失效
这是最硬的约束,不是建议。Bootstrap 5 的 offcanvas 依赖 document.body 插入遮罩层(.offcanvas-backdrop)并绑定事件委托。如果写在 <main></main>、<div class="container"> 或任何带 <code>transform/position: fixed 的父容器里:
- 遮罩层可能插入失败或位置错乱,导致点击无响应
- ESC 键无法关闭(事件监听器没挂到正确层级)
- 滚动时 offcanvas 内容错位,尤其在 iOS Safari 上更明显
- 修复方式只有一种:把
<div class="offcanvas"> 移到 <code>直接子级,并确保 id 唯一且与data-bs-target完全匹配data-bs-toggle和data-bs-target配对失败,是“点了没反应”的头号原因按钮和 offcanvas 实例之间靠属性联动,不是靠 class 或 DOM 位置。常见断连场景:
- 按钮写
data-bs-target="#nav-sidebar",但 offcanvas 的 id 是id="sidebar-nav"(拼写/顺序不一致) - 用了
href="#nav-sidebar"却漏掉data-bs-toggle="offcanvas"(二者缺一不可) - 升级 v4 → v5 时,把
data-toggle="offcanvas"忘了改成data-bs-toggle="offcanvas" - 目标 offcanvas 元素尚未被 JS 加载(比如动态注入),而按钮已渲染 —— 此时需手动
new bootstrap.Offcanvas(...)初始化
offcanvas-body不设max-height和overflow-y: auto,内容会撑爆视口offcanvas 默认不限制内部高度,长列表、表单或嵌套导航极易导致关闭按钮滑出可视区,甚至遮挡底部操作按钮:
- 必须给
<div class="offcanvas-body"> 显式设置 <code>max-height: calc(100vh - 80px)(减去 header 高度) - 加
overflow-y: auto,否则滚动失效;iOS Safari 推荐用100dvh替代100vh避免地址栏遮挡 - 别在 offcanvas-body 里再套
position: absolute或transform元素 —— 它们会脱离 offcanvas 的 transform 容器,定位漂移 - 若需顶部固定 header(如带关闭按钮的 bar),应单独用
<div class="offcanvas-header">,不要混进 body<h3>方向类写错、混用或动态切换,会导致行为不可预测</h3> <p>方向由 class 控制,不是 data 属性,且严格互斥:</p> <ul> <li>左滑抽屉必须用 <code>offcanvas-start(不是offcanvas-left,后者是 v4 遗留名) - 右滑用
offcanvas-end;上下分别用offcanvas-top/offcanvas-bottom - 不能同时写
offcanvas-start offcanvas-end,也不会自动 fallback - 不支持运行时切换方向:改 class 不生效,必须销毁实例后重建(
instance.hide(); new bootstrap.Offcanvas(...)) - RTL 页面下
offcanvas-start自动对应右侧,无需额外处理
真正难的不是写对 class,而是理解 offcanvas 的定位模型 —— 它本质是脱离文档流的模态层,所有样式干预(margin/translate/z-index/position)都容易破坏其与 backdrop 的协同逻辑。桌面端要固定侧边栏,该用栅格(
col-3 col-9)+d-none d-md-block;移动端收起才交给 offcanvas,这才是它设计的使用路径。 - 按钮写











