直接加 collapse 类没动画是因为Bootstrap 5未定义height过渡,需补CSS transition及JS动态设高度:监听show/hidden事件,用getComputedStyle读高、setTimeout触发渲染、内联style.height控制过渡。

为什么直接加 collapse 类没动画?
Bootstrap 5 默认的 collapse 组件展开/收起是瞬间切换的,因为它的 CSS 只控制 height 和 visibility,但没配 transition。你看到的“没动画”,其实是它压根没定义过渡行为。
解决办法不是换 JS,而是补上几行关键 CSS —— 而且必须用 height + overflow 配合,不能只靠 opacity 或 max-height(后者有精度问题)。
- 必须给
.collapse元素设height: 0和overflow: hidden初始态 - 展开时 Bootstrap 会加
.show类,并把height设为auto;但auto无法过渡,所以得用 JS 动态读取真实高度再设死 - 因此真正平滑的关键,在于用
getComputedStyle读高、再用style.height写入具体像素值
怎么用原生 JS 补上 height 过渡逻辑?
Bootstrap 5 的 collapse 事件足够用:show.bs.collapse 触发时读高,shown.bs.collapse 清除内联 height 避免影响后续操作。
document.addEventListener('show.bs.collapse', e => {
const target = e.target;
const height = getComputedStyle(target).height;
target.style.height = '0';
setTimeout(() => target.style.height = height, 10);
});
document.addEventListener('shown.bs.collapse', e => {
e.target.style.height = '';
});
注意:这里用了 setTimeout 是为了强制浏览器先渲染 height: 0,再设目标高度,否则过渡不触发。别用 requestAnimationFrame 替代——在某些版本 Bootstrap 中会抢在 class 更新前执行,导致失效。
CSS 里必须写的三行过渡规则
光靠 JS 不够,CSS 得明确告诉浏览器哪些属性要过渡。下面这三行缺一不可:
.collapse {
transition: height 0.35s ease, visibility 0.35s ease;
}
.collapse:not(.show) {
visibility: hidden;
}
-
height过渡负责伸缩感,visibility配合避免鼠标穿透或焦点残留 - 不要加
overflow到transition属性里 —— 它不支持过渡,强行写会导致整个 transition 失效 - 如果面板里有
margin或padding,它们不会参与 height 过渡,需额外用margin-bottom动画模拟(但通常没必要)
用 data-bs-parent 时动画错乱怎么办?
多个折叠面板互斥(比如手风琴)时,Bootstrap 会在展开新面板前先收起旧的 —— 但默认逻辑会跳过 show.bs.collapse 事件,直接设 height: 0,导致过渡被绕过。
修复方式是监听 hide.bs.collapse 并手动补 height:
document.addEventListener('hide.bs.collapse', e => {
e.target.style.height = getComputedStyle(e.target).height;
setTimeout(() => e.target.style.height = '0', 10);
});
这个 trick 的关键是:让「收起」也走一遍和「展开」对称的流程。否则你会看到一个面板啪地消失,另一个慢慢展开,节奏完全不一致。
实际项目里最容易被忽略的是:所有这些 JS 必须在 Bootstrap 的 collapse 初始化之后运行,否则事件监听器挂不上。如果你用模块化引入,确保脚本在 bootstrap.bundle.js 后执行。











