CSS中max-height动画需用具体像素值,因none和auto不可插值;须用scrollHeight获取真实高度,配合offsetHeight强制重排,并分步设置max-height起止值,同时限定transition属性并可选will-change优化。

为什么直接用 max-height: 0 → max-height: none 没动画
浏览器根本不会对 none 做插值计算,它不是数值,无法参与 CSS 过渡。你写的 transition: max-height 0.3s 在遇到 none 时直接跳转,看起来就是“啪”一下弹出来。同理,auto 也不行——它不是可动画的长度单位。
必须用具体像素值,且得靠 JS 动态读取 scrollHeight
目标 max-height 必须是真实内容高度,不能硬写死(比如 200px),否则行数一变就卡顿或留白。关键点:
-
scrollHeight是唯一能准确反映完整内容高度的属性;offsetHeight和clientHeight都只含可见区域,不含溢出部分 - 展开前先设
max-height: 0+overflow: hidden,再调用el.offsetHeight强制触发一次重排(让浏览器“看到”当前是收起态) - 紧接着把
max-height设为el.scrollHeight,动画才真正开始
收起时也要“先读再设”,否则会跳
收起不是简单设 max-height: 0 就完事。如果当前是展开态,但 max-height 是个大值(比如 324px),而你直接设 0,浏览器可能因优化跳过中间帧。正确做法:
- 收起前,先用
getComputedStyle(el).maxHeight读出现有值(比如"324px") - 立即设成这个值(确保过渡起点明确)
- 再设
max-height: 0,并保持overflow: hidden
transition 不要写 all,只锁死 max-height 和 overflow
transition: all 0.3s 看起来省事,但容易引发意外重绘,尤其当元素内有图片、字体加载或伪元素时。更稳妥的是:
立即学习“前端免费学习笔记(深入)”;
transition: max-height 0.3s ease-in-out, overflow 0.3s-
overflow加过渡是为了避免收起末尾出现滚动条闪现 - 别忘了加
will-change: max-height(可选),在长列表中能轻微提升动画帧率
offsetHeight 或类似触发 layout 的属性,JS 设置完初始 max-height: 0 后,浏览器可能把后续设置合并渲染,导致整个动画被跳过。


















