bootstrap 4 不支持 .is-fixed 类,其 modal.js 无视该类;补偿逻辑仅修改 body 内联 padding-right,无法通过 css 覆盖;最稳妥方案是使用 data-backdrop="static" 跳过补偿。

Bootstrap 4 没有 .is-fixed 类,别白加
Bootstrap 4 的 modal.js 根本不识别 .is-fixed —— 这个类是 Bootstrap 5+ 才引入的。你在 BS4 项目里给 <nav class="fixed-top is-fixed"></nav> 加这个类,JS 完全无视,抖动照旧。BS4 的补偿逻辑只改 body 的 padding-right,且不提供任何钩子让 fixed 元素同步响应。
直接覆盖 body 内联 padding-right 是徒劳的
BS4 在 show 时用 document.body.style.paddingRight = width + 'px' 写内联样式,优先级高于所有 CSS 规则。body { padding-right: 0 !important } 不起作用,反而可能在 modal 关闭后残留错误值,导致后续滚动异常。
- 检查控制台 Elements 面板,确认
body上是否出现style="padding-right: 17px"这类内联样式 - 不要写
.modal-open { padding-right: 0 !important }—— 这个类本身不带 padding,纯属无效靶子 - 禁用浏览器开发者工具里的
overflow: hidden,看抖动是否消失:如果消失,说明问题确实出在补偿逻辑上
BS4 最稳妥的解法:用 data-backdrop="static" 跳过补偿
这是唯一不需要改 JS、不依赖第三方库、兼容所有 BS4 版本(v4.0–v4.6)的轻量方案。它让 modal 完全跳过滚动条宽度检测、modal-open 类添加、padding-right 注入和 overflow: hidden 设置,只保留遮罩层和 ESC 关闭能力。
- 只需在 modal 根元素加属性:
<div class="modal" data-backdrop="static"> <li>它不影响键盘操作:<code>ESC仍可关闭,focus流也正常 - 如果你必须支持点击遮罩关闭,就别用这个方案——BS4 没有安全接管补偿的 API,手动监听
show.bs.modal并同步 fixed 元素 padding 的成本远高于换方案 - 监听
show.bs.modal:读取真实滚动条宽度(getScrollbarWidth()可参考 BS4 源码实现),然后同时设置document.body.style.overflow = 'hidden'和所有 fixed 元素的style.paddingRight - 监听
hidden.bs.modal:还原body.style.overflow为''(空字符串,不是'auto'),并清空所有 fixed 元素的paddingRight - 多层 modal 时,必须用
$('.modal.show').length判断是否还有可见 modal,不能只靠modal-open类是否存在
真要保留点击遮罩关闭?只能手写滚动控制
BS4 不提供 checkScrollbar 替换入口,也不暴露滚动条宽度计算逻辑。想稳住 fixed 元素,你得完全绕过它的自动流程:
真正难的不是写这几行代码,而是排查有没有其他脚本(比如全局重置 CSS、perfect-scrollbar 初始化)悄悄覆盖了 body 的 overflow 或内联 padding-right —— 这些干扰项往往比逻辑本身更耗时间定位。











