height: auto 无法 transition 是因非数值属性,浏览器无法插值;推荐用 grid-template-rows: 0fr → 1fr 替代,配合 overflow: hidden 和 display: grid 实现平滑动画。

为什么 height: auto 不能直接 transition
浏览器根本不会对 height: auto 做插值计算——它不是数值,而是布局阶段动态推导出的结果。你写 height: 0 → height: auto,动画引擎看到的是 “0 → ?”,中间帧无从生成,结果就是硬切。DevTools 里能看到高度瞬间跳变,transition 形同虚设。
用 grid-template-rows: 0fr → 1fr 替代 height 控制
这是目前兼容性好、无需 JS、真正平滑的方案,核心是绕过 height 属性本身:
- 父容器必须声明
display: grid,且有明确的高度上下文(比如由内容撑开,或设了min-height) - 需要伸缩的内容必须独占一行,用
grid-template-rows控制该行 - 收起态写
grid-template-rows: 0fr,展开态写grid-template-rows: 1fr(或minmax(0, max-content)) - 必须加
overflow: hidden,否则内容可能溢出影响视觉 - 过渡写在
grid-template-rows上:transition: grid-template-rows 0.3s ease
示例片段:
.accordion {
display: grid;
grid-template-rows: 0fr;
overflow: hidden;
transition: grid-template-rows 0.3s ease;
}
.accordion.open {
grid-template-rows: 1fr;
}
Chrome 129+ 可直接用 calc-size(auto),但别急着删 Grid 方案
新特性确实存在:height: calc-size(auto) + transition: height 能工作,:root { interpolate-size: allow-keywords } 更能全局启用 height: auto 动画。但要注意:
立即学习“前端免费学习笔记(深入)”;
- 仅 Chrome 127+(需开启实验 flag)和 129+ 稳定版支持,Firefox/Safari 尚未跟进
-
calc-size()不支持嵌套函数,如calc-size(max-content + 1rem)在部分版本会失败 - Grid 方案在所有现代浏览器中已稳定运行多年(Chrome 66+ / Firefox 70+ / Safari 16.4+),更可控
- 如果内容含异步加载、字体加载延迟、或
line-height动态变化,calc-size(auto)可能取到不准确的初始高度
别踩 max-height 模拟的坑
虽然 max-height 是最老的 fallback 方案,但实际容易翻车:
- 设太小:内容被截断;设太大(如
max-height: 1000px):动画末段明显“拖尾”,因为最后几十像素过渡变慢 - 不能用
max-height: none或max-height: fit-content,它们不可插值 - 响应式场景下,同一元素在不同屏幕宽度中真实高度差异大,一个固定
max-height值很难兼顾 - 若内容内有
transform或position: absolute元素,max-height无法约束其布局影响
Grid 方案天然规避这些——它依赖的是内容实际渲染后的 max-content 高度,不是预估。
font-display: optional 都可能导致展开后高度微调。这时候,grid-template-rows: minmax(0, max-content) 比 1fr 更鲁棒,但也要注意 Safari 对 max-content 的插值支持略晚于 1fr。


















