max-height 是当前最优解,因其是连续可动画值且兼容性好,配合 overflow: hidden 实现平滑过渡;而 height: auto 和 display 无法触发 css 过渡。

max-height 是唯一可靠、兼容性好且无需 JS 就能触发平滑过渡的 CSS 属性,但直接设 height: auto 或依赖 display 切换必然失败。
为什么 max-height 是当前最优解
浏览器无法对 height: auto 插值,display 属于离散属性,transition 完全不生效。而 max-height 是连续可动画值,配合 overflow: hidden 能自然截断内容,形成“拉伸/收缩”视觉效果。
常见错误现象包括:点击后内容瞬间闪现、高度不动只透明度变、收起时底部悬停半秒才消失——基本都源于 max-height 值设得过大或过小,或漏写了 overflow: hidden。
-
max-height必须显式声明起止值(如0→400px),不能靠all 0.3s模糊过渡 - 静态内容(如固定菜单项)可设安全上限,比如
max-height: 420px(比最大可能高度多 20–30px) - 动态内容(如 API 渲染的列表)必须用 JS 读
element.scrollHeight后赋值,否则动画会中断或裁切 -
overflow: hidden要写在初始和展开两个状态共用的类里,不能只加在.open中
JS 动态设置 max-height 的关键时机
不是“加类 → 设 height”,而是“加类 → 强制重排 → 设 max-height”,否则浏览器跳过首帧动画。
典型疏漏是用 getComputedStyle(el).maxHeight === '0px' 判断状态——该值受缓存影响,不可靠;应始终用 el.classList.contains('open')。
- 展开前:先加
open类,再读一次el.offsetHeight(触发重排),再设el.style.maxHeight = el.scrollHeight + 'px' - 收起时:先设
el.style.maxHeight = el.scrollHeight + 'px',再移除open类,最后在 transitionend 后清空style.maxHeight - 若内容含图片或字体加载中,需监听
load或用fontfaceobserver确保 scrollHeight 准确
替代方案的适用边界
transform: scaleY(0) 性能更好(GPU 加速),但会压缩子元素内联样式(如 border、padding 视觉失真),且无法配合 overflow: hidden 精确裁剪,适合纯文本折叠。
clip-path 动画顺滑、支持任意形状裁剪,但 Safari 旧版本兼容差,且无法与 scrollHeight 动态联动。
-
details/summary标签是纯 CSS 方案,零 JS,但无法自定义展开逻辑(如多开、手风琴互斥)、不支持过渡动画 - 用
grid-template-rows控制行高动画可行,但仅适用于单行内容或固定结构,灵活性极低 - 所有方案都绕不开一个事实:只要内容高度不确定,就必须靠 JS 测量,CSS 本身没有“自动适配高度动画”的能力
iframe 时,scrollHeight 是否还准确——这时候得考虑 ResizeObserver 监听内部尺寸变化,而不是只在点击时测一次。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











