根本原因是bootstrap 5的js行为与css类名生命周期未对齐;动画类必须在show.bs.modal中添加、hidden.bs.modal中清除,且需配合animate__animated基础类和正确选择器作用域(如.modal.fade .modal-dialog)才能触发重绘。

根本原因不是你写错了动画,而是 Bootstrap 5 的 JS 行为和 CSS 类名生命周期没对齐——动画类必须在正确时机增删,否则浏览器压根不触发重绘。
为什么直接加 animate__slideInUp 没反应
Bootstrap 5 的模态框、折叠面板、轮播图等组件都靠 JS 动态添加/移除 .show 类来控制显隐,而 animate.css 这类动画库依赖类名“变化”(add/remove)来启动 animation。如果你只是把 animate__slideInUp 写死在 HTML 里:
-
class="modal-dialog animate__slideInUp"→ 只播一次,第二次打开无动画 - 没加
animate__animated基础类 → 所有animate__*类无效 - HTML 根元素漏了
fade类 →show.bs.modal事件不触发,监听白搭
必须监听 show.bs.modal 和 hidden.bs.modal 事件
动画要每次打开都重播,就得在 DOM 就位、但动画尚未开始时注入类;关闭后还得及时清理,否则类堆积导致跳帧或静默失效:
- 在
show.bs.modal里:用element.classList.add('animate__animated', 'animate__slideInUp') - 在
hidden.bs.modal里:用element.classList.remove('animate__animated', 'animate__slideInUp') - 别用 jQuery 的
addClass直接操作——它不保证动画重置,除非你额外监听animationend
选择器作用域错位:动画只对 .modal.fade .modal-dialog 生效
Bootstrap 5 的过渡逻辑硬编码在这一选择器链上,给其他元素加 transition 或 animation 都是徒劳:
-
.modal、.modal-content、.modal-body上设transition→ 完全无效 -
.modal.fade .modal-dialog必须显式声明transform和opacity的transition,例如:transition: transform 0.4s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.4s ease-out - 遮罩层
.modal-backdrop要单独处理,否则会“啪”一下闪出来
自定义 @keyframes 动画被覆盖的真相
比如改进度条条纹动画,你以为重写 @keyframes progress-bar-stripes 就行了?错。它必须满足两个硬条件:
- 你的 CSS 文件必须在 Bootstrap CSS 之后加载(查「查看页面源代码」确认
<link>顺序) - 选择器权重得够——
.progress-bar.animated比单纯.progress-bar更稳,避免被 Bootstrap 原生规则压制 - 别忘了显式给
.progress-bar加animation: progress-bar-stripes 1s linear infinite,仅靠类名不会自动启用
最容易被忽略的是:动画类清理不是可选项,是必选项。哪怕用了 animate.css,只要没在 hidden.bs.modal 里清除,下次打开时浏览器大概率跳过动画——因为类名还在,帧已缓存,animation 不重播。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











