height: auto 无法参与 transition,因 auto 非可插值数值;应改用 max-height 或 JS 动态设置真实高度,并注意过渡后清理内联 height 值以防布局异常。

height: auto 为什么不能加 transition
直接写 transition: height 0.3s + height: auto 是无效的。因为 auto 不是一个可插值的数值单位,浏览器无法在 “height: 0” 和 “height: auto” 之间生成中间帧,动画会直接跳变或完全不触发。
常见错误现象包括:hover 展开时“啪”一下弹出来、JS 切 class 后高度瞬间变化、控制台没报错但就是不动。
- height: auto 只能用于布局计算,不能参与过渡
- display: none / block 也不可过渡,必须避开
- 起始/结束状态都得是明确的像素值(或 rem/em 等相对单位),且类型一致
用 max-height 替代 height 实现平滑展开
这是最轻量、纯 CSS 的解法,适合内容高度可预估的场景(比如下拉菜单、折叠面板)。
原理是:把 max-height 当作“高度代理”,初始设为 0,展开时设为一个足够大的固定值(如 500px),配合 overflow: hidden 隐藏溢出内容。
立即学习“前端免费学习笔记(深入)”;
- 初始状态:
max-height: 0; overflow: hidden; - 展开状态:
max-height: 500px;(需大于内容实际高度) - 必须加
overflow: hidden,否则内容会撑开容器并显示滚动条 - 过渡时长建议 0.25s–0.35s,太长显得迟滞,太短看不清过程
JS 动态计算真实高度实现精准过渡
当内容高度不可预测(比如富文本、动态列表、多行 textarea),max-height 容易设小导致截断、设大会拖慢动画,这时就得靠 JS 获取真实 scrollHeight。
关键步骤不是“设 height”,而是“先设 height: 0 → 强制重排 → 再设目标高度”,否则浏览器会跳过过渡。
- 展开前先加 class 触发
height: 0,然后调用element.offsetHeight强制同步布局 - 再设置
element.style.height = element.scrollHeight + 'px' - 收起时反向操作:先设目标高度 → offsetHeight → 再设
height: 0 - 收起后记得监听
transitionend事件,移除内联height并恢复height: auto,否则后续 JS 计算会出错
textarea 高度自适应要绕开 overflow-y 冲突
textarea 天然支持 scrollHeight,但直接改 style.height 容易和 overflow-y: auto 冲突,导致滚动条闪现或高度不准。
稳妥做法是:始终设 overflow-y: hidden,只靠高度变化暴露内容,避免滚动行为干扰动画逻辑。
- 初始化时:
textarea.style.cssText = 'height: 50px; overflow-y: hidden;' - input 事件中:
textarea.style.height = 'auto'; textarea.style.height = textarea.scrollHeight + 'px'; - 不要用
min-height或max-height混合控制,它们和height同时存在时优先级容易混乱 - 移动端注意 iOS Safari 对
scrollHeight的延迟更新,必要时加setTimeout(..., 0)微任务兜底
height 值。它会锁死元素高度,导致后续 JS 插入新内容、窗口 resize、甚至父容器 flex 布局重新计算都失效——问题不报错,但表现诡异,排查起来特别费时间。



















