默认行为是不滚动,若背景可滚、卡住或关闭后仍不可滚,说明 bootstrap 滚动锁定被干扰;根本原因是 modal-open 类未正确添加/移除,或被 css 覆盖,或多层 modal 导致误删,需通过 js 实例控制并检查 dom 状态。

默认行为就是不滚动——但如果你发现背景还能滚、或者滚完卡住、或者关了模态框还不能滚,说明 Bootstrap 的滚动锁定机制被干扰了,不是没生效,而是没管住。
为什么 background 还能滚动?检查 modal-open 类有没有被加到 body
Bootstrap 5 依赖 body 上的 modal-open 类来禁用滚动,它会同时设 overflow: hidden 和补偿 padding-right。如果这个类没出现,滚动就完全不受控。
- 别手动调用
element.classList.add('modal-open')—— 必须由 Bootstrap 的 JS 实例触发,比如用bootstrap.Modal.getInstance(modalEl).show() - 确认没在其他地方(比如全局 CSS 或第三方插件)写了
body { overflow: visible !important },这会直接覆盖modal-open的样式 - 检查是否用了自定义初始化方式:比如直接
modalEl.classList.add('show')+modalEl.style.display = 'block',这种绕过 JS 控制流的做法会让modal-open完全缺失
hidden.bs.modal 触发后 body 滚动没恢复?多层 Modal 是重灾区
Bootstrap 默认逻辑是“任意一个 modal 关闭 → 移除 modal-open → body 恢复滚动”,但在嵌套场景下,上层 modal 还开着,底层 modal 关闭就会误删 modal-open,导致背景意外可滚。
- 不要靠
document.body.classList.contains('modal-open')判断是否该恢复,改用document.querySelectorAll('.modal.show').length > 0 - 监听
hidden.bs.modal事件时,先检查是否还有其他 modal 在显示:$('#myModal').on('hidden.bs.modal', function () { if ($('.modal.show').length === 0) { document.body.classList.remove('modal-open'); } }); - 避免在关闭逻辑里写
$('body').removeClass('modal-open'),jQuery 可能因异步或 DOM 状态不同步漏操作
想彻底禁用滚动补偿(避免“向左跳”),用 data-bs-backdrop="static"
页面抖动的根源不是滚动被禁,而是 Bootstrap 主动加的 padding-right 补偿。这个补偿只对非 static backdrop 生效,而 static 模式会跳过整个补偿链路。
- 加属性即可:
<div class="modal" data-bs-backdrop="static"> —— 不影响 ESC 关闭,只停用点击遮罩关闭和 padding 注入<li>如果业务必须支持点击遮罩关闭,就别用这个方案;否则这是最干净、副作用最小的解法</li> <li>注意:<code>data-bs-backdrop="static"不影响modal-open类的添加/移除,滚动锁定依然有效,只是没有视觉偏移 - 只给
.modal-body加max-height: 60vh+overflow-y: auto,不要碰.modal-dialog或.modal-content的 height - 移动端 Safari 要加
-webkit-overflow-scrolling: touch才有惯性滚动 - 如果用了
modal-fullscreen,记得把.modal-body的max-height改成calc(100dvh - 120px)(减去 header/footer 高度),避免 iOS 视口缩放 bug
.modal-body 内容超长却不滚动?高度边界没设对
很多人以为禁了 body 滚动,modal 就自动可滚,其实 modal 本体默认 overflow: hidden,.modal-body 必须有明确的高度约束才能激活内部滚动。
真正难处理的是多层 Modal + 自定义滚动容器 + 第三方插件共存的场景——这时候 modal-open 的生命周期、滚动条宽度探测、fixed 元素补偿三者容易错位,单靠 CSS 覆盖基本无效,得从事件钩子和 DOM 状态判断入手。











