css transition 对 grid-template-rows/columns 无效,因其值为不可插值的结构化轨道定义;可靠方案是用 max-height 控制内容显隐、transform 移动网格项,或 chrome 115+ 中通过 @property + calc() 限定条件实现数值化动画。

grid-template-rows / grid-template-columns 改变时,transition 不生效
直接改 grid-template-rows 或 grid-template-columns 的值,CSS transition 完全没反应——这不是你写错了,是浏览器根本不支持对这些属性做过渡动画。
原因很实在:这类属性的值是“轨道定义”,比如 "100px 1fr 200px",它不是单一数值,而是结构化描述;浏览器没法在两组不同数量、不同单位、不同函数(minmax()、fit-content())之间插值计算中间状态。
- 支持过渡的 Grid 相关属性极少,只有
grid-row-start、grid-column-end等定位类属性(且仅限于数值型值,如2→4) -
grid-area也不行,因为它本质是四个定位属性的简写,一旦涉及字符串(如"header")就彻底无法插值 - 别试
transform: scale()模拟,网格项会变形,但轨道间隙、对齐逻辑全乱
用 grid-auto-rows + max-height 配合 overflow 实现“高度伸缩”动画
想让某一行内容展开/收起并带动画?绕过 grid-template-rows,转而控制子元素自身高度和容器的隐式轨道。
核心思路:让目标区域用 grid-row 占据固定行号,但内容容器用 max-height + overflow: hidden 控制显隐,再配合 transition。
立即学习“前端免费学习笔记(深入)”;
- 父容器设
grid-auto-rows: min-content,避免隐式行高塌缩干扰 - 目标子项外层加 wrapper,设
max-height: 0/max-height: 300px,搭配transition: max-height 0.3s ease - 注意
max-height必须设具体数值(不能是none或fit-content),否则过渡无效 - 如果内容高度不确定,可用 JS 先
getBoundingClientRect().height测高,再设max-height
/* 示例:点击展开第二行内容 */
.container { display: grid; grid-template-rows: auto; }
.item-2 { grid-row: 2; }
.item-2 > .wrapper {
max-height: 0;
overflow: hidden;
transition: max-height 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
.item-2.active > .wrapper { max-height: 200px; }用 CSS 自定义属性 + @property 声明可动画的网格轨道(Chrome 115+)
新版 Chrome 支持通过 @property 把自定义属性注册为可过渡类型,从而间接驱动 grid-template-rows 动画——但限制极多,只适合简单场景。
它不改变底层限制,只是把“字符串插值”转成“数值插值”,所以只能用于纯数字单位(如全用 px),且轨道数必须固定。
- 必须提前声明
@property --row-1 { syntax: "<length>"; inherits: false; initial-value: 100px; }</length> -
grid-template-rows写成calc(var(--row-1) * 1) calc(var(--row-2) * 1) 100px,靠calc()强制触发数值计算 - 旧版 Safari / Firefox 不支持
@property,降级方案仍需回退到max-height方案 - 一旦用了
fr、minmax()或响应式单位(em、rem),整个链路立刻失效
真正稳定的方案:用 transform 移动网格项,而非重排轨道
如果你要的是“视觉上某块区域滑入/滑出”,而不是“网格结构本身伸缩”,那最稳的做法是不动 grid-template-*,只动项的位置和尺寸。
利用 Grid 的定位能力 + transform,既保持布局上下文稳定,又获得硬件加速动画。
- 给目标项设
grid-row: 2 / 3固定位置,再用transform: translateY(-100%)移出视区 - 触发动画时改
transform: translateY(0),配合transition: transform 0.3s ease-out - 需要“推挤其他项”效果?加
margin-bottom动画,但注意 margin 不支持height类插值,得用max-height配合 - 所有现代浏览器都支持,无兼容性包袱,性能也比重排 layout 好得多
Grid 轨道大小动画的本质矛盾在于:CSS 过渡要求可插值,而 Grid 轨道定义天生不可插值。绕不开这个前提,任何“直接过渡 grid-template-*”的尝试都会静默失败。能跑起来的,全是借力打力——要么控内容高度,要么移元素位置,要么靠新 API 限定条件硬刚。选哪个,取决于你要动的是“结构”还是“视觉”。










