css 原生不支持从 height: 0 到 height: auto 的平滑过渡,因为 auto 不是数值,无法计算中间状态。要实现这一效果,必须使用 javascript 获取目标高度并赋值给 css transition 属性。

为什么 height auto 无法直接过渡
浏览器在渲染时,只有当两个值都是确定的数字(如像素、百分比)时,才能进行插值动画。将 height 设置为 auto 意味着由内容决定高度,这是一个动态且未知的值,因此浏览器会跳过过渡阶段,直接应用最终样式,导致展开或收起时出现“跳变”而非“滑动”。

const element = document.querySelector('.box');
// 获取当前实际高度
const currentHeight = element.scrollHeight;
// 设置初始状态为 0
element.style.height = '0';
element.style.overflow = 'hidden';
// 强制重绘以应用初始状态
void element.offsetHeight;
// 添加过渡类
element.classList.add('expanded');
// 在 CSS 中定义 .expanded { height: ${currentHeight}px; }如何正确实现平滑展开与收起
正确的做法是先用 JavaScript 读取元素的内容高度(scrollHeight),然后将其作为具体的像素值赋给 height 属性,同时配合 overflow: hidden 隐藏溢出内容。这样浏览器就能在 0 和具体像素之间进行平滑插值。收起时同理,从具体像素过渡回 0。
立即学习“前端免费学习笔记(深入)”;

// 收起逻辑示例
function collapse(element) {
const currentHeight = element.scrollHeight;
element.style.height = `${currentHeight}px`;
// 强制重绘
void element.offsetHeight;
element.style.transition = 'height 0.3s ease';
element.style.height = '0';
}
// 展开逻辑示例
function expand(element) {
const targetHeight = element.scrollHeight;
element.style.height = '0';
void element.offsetHeight;
element.style.transition = 'height 0.3s ease';
element.style.height = `${targetHeight}px`;
}处理动态内容变化时的注意事项
如果元素内部内容会动态变化(如 AJAX 加载数据),必须在每次内容更新后重新计算 scrollHeight。如果在过渡过程中内容发生变化,可能导致高度计算不准确。建议在内容稳定后再触发高度动画,或者使用 ResizeObserver 监听内容变化并重置动画状态,确保始终基于最新的内容高度进行过渡。


















