Bootstrap 5 模态框滑入动画必须添加 .fade 类才能生效,否则仅靠 .show 会硬切;需确保根元素含 class="modal fade",并覆盖三处 CSS 规则、显式声明 transition 属性,监听事件动态添加 animate.css 类。

Bootstrap 5 模态框滑入动画必须加 .fade 类才能生效
不加 .fade,JS 切换 .show 时只会硬切(display: block 瞬间出现),transition 完全不触发。这是最常被忽略的前提——哪怕你写了完整的 transform + transition 规则,HTML 结构里漏掉 fade,动画就等于没写。
检查你的模态框根元素是否包含这两个类:class="modal fade"。不是只加在 .modal-dialog 上,也不是用 data-bs-fade——Bootstrap 5 不认这个属性,它只靠 class 名字匹配 CSS 选择器。
覆盖默认滑入动画要重写三处 CSS 选择器
Bootstrap 默认的滑入是 translateY(-50px) → 0,但你想改成从底部上滑、从左侧平移或带缩放,就得精准覆盖以下三处规则,缺一不可:
-
.modal.fade .modal-dialog:定义初始状态(如transform: translateY(100%); opacity: 0;) -
.modal.fade.show .modal-dialog:定义最终状态(如transform: translateY(0); opacity: 1;) -
.modal.fade或.modal.fade .modal-backdrop:确保遮罩层同步动,否则 backdrop 会“啪”一下闪出来
别只改 .show,初始态没设对,动画第一帧就跳变;也别漏掉 backdrop,它的 .fade 和 .show 是独立控制的。
transition 属性必须显式声明,不能依赖 all
写成 transition: all .3s ease-out 在 Safari 下容易出问题:浏览器可能把 display、visibility 甚至 z-index 也纳入过渡,导致闪烁或卡顿。正确做法是指定关键属性:
transition: transform .3s cubic-bezier(0.22, 0.61, 0.36, 1), opacity .3s ease-out;
注意两点:
- 必须同时写
transform和opacity,只调一个会导致淡入/位移不同步 - 缓动函数建议用
cubic-bezier(0.22, 0.61, 0.36, 1)(Bootstrap 默认值),比ease-out更稳,尤其在低端安卓 WebView 中
用 animate.css 时要在 show.bs.modal 事件中动态加类
直接给 .modal-dialog 写死 animate__slideInUp 没用——因为 Bootstrap 的 .show 类是 JS 后加的,CSS 动画不会自动重播。必须监听事件,在 DOM 就位但动画未启时注入类:
document.getElementById('myModal').addEventListener('show.bs.modal', function () {
const dialog = this.querySelector('.modal-dialog');
dialog.classList.remove('animate__animated', 'animate__slideInUp');
dialog.classList.add('animate__animated', 'animate__slideInUp');
});
还要配一个清理逻辑,避免多次打开后类堆积:
在 hide.bs.modal 或 hidden.bs.modal 里调用 classList.remove()。如果用了 v4+ 的 animate.css,且用户开启了「减少运动」系统偏好,动画会被静音——需要手动加 prefers-reduced-motion: no-preference 媒体查询兜底。
真正难的不是写几行 CSS,而是搞清 Bootstrap 的动画链路:JS 只管切类,CSS 才是动画本体,而 .fade 是整条链的总开关。漏掉它,后面所有 transition 都是空中楼阁。


















