grid 不支持 grid-template-rows 高度过渡,因 fr 等值无法插值;推荐 max-height + overflow 方案(兼容好),次选 transform: scaley()(性能优但有模糊风险);若强制用 grid 行高动画,须 js 获取并设置绝对高度值,注意节流防重排。

Grid 本身不支持 height 过渡,因为 grid-template-rows 是离散值(比如 1fr、auto、0px),无法插值动画。直接对 height 或 grid-row-start/grid-row-end 加 transition 都无效。
用 max-height + overflow 模拟展开收起
这是最常用且兼容性好的方案,适用于内容高度不确定但有合理上限的场景:
-
max-height设为一个明显大于内容实际高度的固定值(如500px),不能用none或fit-content—— 它们无法参与过渡 - 初始状态设
max-height: 0+overflow: hidden,隐藏内容 - 展开时设
max-height: 500px,CSS 会线性过渡这个数值 - 注意:如果内容真实高度超过
max-height上限,会截断;过小则动画“冲过头”,显得不自然
.accordion-panel {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s ease-in-out;
}
.accordion-panel.is-open {
max-height: 500px; /* 要比最大可能内容高,但别过大(影响动画时长感) */
}
用 transform: scaleY() 配合 origin
适合容器有明确高度、或可接受轻微缩放形变的场景,性能优于 max-height(GPU 加速):
- 初始设
transform: scaleY(0)+transform-origin: top(保证从顶部展开) - 展开时设
transform: scaleY(1),配合transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1) - 必须加
overflow: hidden,否则缩放过程中内容会溢出 - 缺点:文字在缩放过程中可能轻微模糊(尤其低 DPI 屏幕),且无法精确控制“展开完成时的高度”
Grid 内真正动态行高?得靠 JavaScript 配合 getComputedStyle
如果必须用 Grid 的 grid-template-rows 实现“原生行高过渡”,目前没有纯 CSS 方案。可行路径是 JS 控制:
- 监听展开状态变化,用
getComputedStyle(el).height获取目标高度(需先el.style.display = "block"并offsetHeight强制重排) - 将该高度写入
grid-template-rows,例如grid-template-rows: 0fr 248px→grid-template-rows: 1fr 248px - 但
fr单位无法直接过渡,所以得改用px或em等绝对单位,并手动设置transition: grid-template-rows 0.3s - 风险:频繁读写 layout 触发强制同步重排(layout thrashing),尤其在滚动中展开时卡顿明显
真正平滑的关键不在“用什么技术”,而在于是否提前预估了内容高度边界,以及是否规避了 layout thrashing。多数情况下,max-height 是最稳的选择;追求高性能且能接受缩放形变的,选 scaleY;非要用 Grid 行高动画的,JS 控制务必节流 + 缓存高度值。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











