grid 不支持直接对 grid-template-rows 做过渡动画,因其函数式值无可计算中间态;应改用 max-height + overflow 或 transform: scaley() 驱动子元素动画,或仅在 chromium 中试用 @property 实验方案。

Grid 本身不支持动画,直接对 grid-template-rows 做 CSS 过渡会失效——这是绝大多数人卡住的第一步。
为什么 grid-template-rows 无法直接过渡动画
CSS 的 transition 只能作用于可计算的、有明确中间值的属性(如 height、opacity)。而 grid-template-rows: 1fr 0fr 这类函数式定义没有线性插值路径,浏览器无法生成帧间变化;即使写成 grid-template-rows: 24px 0 → 24px 120px,0 和具体像素之间也因“隐式轨道”行为导致过渡中断或跳变。
所以必须绕过 Grid 轨道尺寸本身,改用其他可动画属性来驱动视觉展开/收起。
用 max-height + overflow 模拟折叠动画(兼容性好)
这是最稳妥的做法:保持 Grid 布局结构不变,只让面板内容区承担动画职责。关键点在于把动画逻辑从 Grid 容器下沉到子元素。
-
grid-template-rows固定为auto auto或auto 1fr,不参与动画 - 每个面板项内部用一个
<div class="panel-content"> 包裹真实内容<li>给 <code>.panel-content设置max-height: 0/max-height: 600px+overflow: hidden,再配transition: max-height 0.3s ease-in-out - 注意:
max-height的终值需大于内容最大可能高度(如 600px),不能用max-height: fit-content(不触发过渡)
.accordion-item {
display: grid;
grid-template-rows: auto auto;
}
.panel-trigger { cursor: pointer; }
.panel-content {
max-height: 0;
overflow: hidden;
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.panel-open .panel-content {
max-height: 600px; /* 需预估足够大 */
}
用 transform: scaleY() 实现更流畅的 Grid 内折叠
如果追求更高性能(避免重排)且不需要精确的高度过渡,transform 是更优解。它不触发布局计算,GPU 加速明显,但需配合 origin 和 overflow 控制裁剪。
- 对
.panel-content设置transform: scaleY(0)→scaleY(1) - 必须加
transform-origin: top,否则缩放中心在中点,视觉错位 - 父容器需设
overflow: hidden,否则缩放时内容溢出 - 注意:
scaleY(0)会让子元素内联样式(如vertical-align)失效,慎用于含表格或行内块的复杂内容
.panel-content {
transform: scaleY(0);
transform-origin: top;
overflow: hidden;
transition: transform 0.25s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.panel-open .panel-content {
transform: scaleY(1);
}
用 @property + grid-template-rows 实验性方案(仅 Chromium)
Chrome 115+ 支持通过 @property 注册自定义属性并声明 syntax: "<length>"</length>,从而让 grid-template-rows 中引用该变量时可被过渡。但它不是通用方案,生产环境慎用。
- 需先注册:
@property --panel-height { syntax: "<length>"; inherits: false; initial-value: 0px; }</length> - 然后在 Grid 容器上写:
grid-template-rows: auto var(--panel-height); - 再通过 JS 修改
style.setProperty('--panel-height', '120px')触发过渡 - 当前 Safari / Firefox 不支持
@property用于grid-template-rows,且无法 fallback 到其他动画方式
真正难的不是怎么写动画,而是判断什么时候该放弃 Grid 动画幻想,老实用 max-height 或 transform ——尤其是当面板内容高度动态、需要 SEO 友好或服务端渲染时,强行绑定 Grid 轨道只会让逻辑越来越脆。











