grid-template-rows 不可动画,需用 max-height + overflow 模拟展开;wrapper 设 overflow: hidden 和过渡 max-height,Grid 行定义保持固定(如 1fr auto),动态高度用 JS 读取 scrollHeight 设置,并注意 auto 行的 min-content 塌陷问题。

grid-template-rows 无法直接做展开动画
CSS 的 grid-template-rows 是布局声明,不是可动画属性。你写 grid-template-rows: 0fr 1fr → grid-template-rows: 1fr 1fr,浏览器不会补间过渡,只会突变——这是最常踩的坑。
原因很简单:fr 单位本身没有绝对像素值,浏览器无法计算中间帧;即使换成 px 或 rem,grid-template-rows 仍被规范列为「非可动画 CSS 属性」(见 CSS Transitions § 2.1)。
用 max-height + overflow 模拟 grid 展开动画
想保留 Grid 布局结构又要有平滑展开,得绕开 grid-template-rows 动画,改用高度过渡。关键是让内容容器在折叠时「视觉隐藏但保持 Grid 占位」。
- 给要展开的区域外层加一个 wrapper(比如
<div class="expandable">),它作为 Grid 的一个子项 - wrapper 设置
overflow: hidden和max-height过渡,初始为max-height: 0 - 内容内层设
padding和margin,避免高度塌缩后看不见边距 - Grid 容器本身保持
grid-template-rows: 1fr auto这类固定行定义,不随展开变化
示例关键片段:
立即学习“前端免费学习笔记(深入)”;
.grid {
display: grid;
grid-template-rows: 1fr auto;
}
.expandable {
overflow: hidden;
max-height: 0;
transition: max-height 0.3s ease-out;
}
.expandable.open {
max-height: 500px; /* 设足够大,或用 JS 读取 scrollHeight */
}JavaScript 控制 open 状态更可靠
CSS-only 切换依赖 :hover 或 checkbox hack,交互弱、不可控、不支持键盘焦点。真实项目里基本都要 JS 驱动。
- 监听点击,切换
open类名,而非操作style.gridTemplateRows - 如果内容高度动态(比如文字长度不定),别硬写死
max-height: 500px,改用 JS 测量:el.scrollHeight,再设为max-height - 动画结束(
transitionend)后,可清除内联max-height,回归 CSS 控制,避免影响后续 JS 计算
Grid 布局下要注意行高塌陷问题
当某一行内容被 max-height: 0 收起,它的 Grid 行(比如 auto 行)并不会自动收缩为 0 —— 它仍会保留最小内容高度(min-content),导致空白残留。
解决方法只有两个:
- 把该行定义从
auto改成0fr,并确保 wrapper 有align-self: start,这样空行才真「消失」 - 或者不用 Grid 行控制高度,改用
display: contents让 wrapper 不参与 Grid 格子计算(但兼容性需查 Can I Use)
真正麻烦的从来不是怎么动起来,而是动完之后,那个没被清掉的 min-content 高度和父级 Grid 的隐式对齐逻辑。多测几个内容长度,不然上线才发现底部多出 24px 空白。


















