Bootstrap 5 通过 visibility + opacity + transform 组合替代 display 切换,避免重排、启用 GPU 加速;.fade 类为动画同步必需;需手动调用 handleUpdate() 处理动态内容偏移;CSS 加载与 JS 执行时机必须严格匹配。

因为 Bootstrap 5 不是“删掉 jQuery 就变快”,而是用原生 JS 精准接管 CSS 动画的整个生命周期——从触发时机、属性选择,到状态判断,全都绕开了 display 切换、隐式重排和过渡封装陷阱。
为什么 display: none + show() 会卡顿
jQuery 风格的 $().modal('show') 内部通常先设 style.display = 'block',再加 opacity 过渡。但 display 切换会强制触发浏览器重排(reflow),打断 CSS 动画流水线,GPU 加速直接失效。
Bootstrap 5 改用 visibility: hidden + opacity + transform 组合:
- 三者都属于「仅触发重绘(repaint)」的属性,可被 GPU 加速
-
visibility控制显隐逻辑,不破坏文档流,也不阻断 transition 动画 - 动画开始前就确保元素已渲染、未被父级
display: none硬性隐藏
.modal.fade 必须保留,不能删
这个 class 不是可选装饰,它是 backdrop 和 dialog 动画同步的前提:删掉它,遮罩层(backdrop)可能闪现或淡入滞后,导致视觉撕裂。
立即学习“前端免费学习笔记(深入)”;
即使你加了 animate.css 或自定义 @keyframes,不同步照样白搭。
.fade 类里声明的 transition: opacity .15s ease-in-out, transform .15s ease-in-out 是 JS 监听的依据:
- 必须写全属性:
transition: opacity .15s, transform .15s,不能只写transition: all .15s(部分浏览器无法识别all中的transform) - 原生实现监听
transitionend事件,且只响应目标属性(如opacity),比setTimeout精确得多
动态内容加载后位置偏移?别忘了 handleUpdate()
如果 modal 内容高度是异步加载的(比如 fetch 后插入 DOM),Popper 定位不会自动重算:
- 动画开始前位置是对的,内容撑开后 dialog 偏移,但 backdrop 仍按旧尺寸铺满
- 必须在内容渲染完成后手动调用
myModal.handleUpdate() - 漏掉这步,
transform: translate()依然执行,但基准坐标错了,看起来像“抖动”或“错位”
CSS 加载顺序和 JS 执行时机最容易被忽略
哪怕只差几毫秒,show() 调用时样式未就绪,transition 就会被跳过——这时候动画退化成硬切,所有优化归零。
常见诱因包括:
-
bootstrap.css在bootstrap.bundle.min.js之后加载 - 用了
@import引入 CSS(阻塞 JS 解析) - 初始化代码没等
DOMContentLoaded就执行



















