fr单位无法动画是因为它不是固定长度,浏览器无法插值;必须改用px/em/rem等固定单位或max-height方案。

为什么直接用 grid-template-rows 的 fr 单位做展开动画会失效
因为 fr 是一种**弹性分配单位,不是固定长度**,浏览器无法对它做插值动画——transition 作用于 grid-template-rows 时,只要其中含 1fr、2fr 这类值,动画就会跳变或完全不触发。你看到的“没动画”,其实是浏览器悄悄降级为即时切换。
真正能被平滑过渡的,只有明确的长度单位:px、em、rem、vh,或者 auto(但 auto 本身也不能和数值混搭动画)。
用 grid-template-rows 实现可动画的展开收起,实际可行方案
核心思路:**避开 fr,改用固定高度 + max-height 或 clamp() 配合 grid 布局逻辑**。但如果你坚持用 grid 控制行高,可以这样操作:
- 定义两行显式轨道:
grid-template-rows: [start] 1.2em [content] 0fr [end];→ 收起态让内容行高度为0fr(视觉隐藏),但注意这仍不能动画 - 改用
grid-template-rows: [start] 1.2em [content] 0px [end];收起,展开时设为具体像素值(如3.6em),再加transition: grid-template-rows 0.3s ease; - 关键限制:必须提前知道最大行高对应的像素值(比如每行
1.2em,最多显示 3 行 →3.6em),否则无法写出确定的目标高度 - 配合
overflow: hidden和line-clamp(仅 WebKit)做视觉截断,确保收起时只显示首行
max-height + grid 容器的组合更实用
多数场景下,与其硬刚 grid-template-rows 的动画限制,不如把 grid 当布局容器,动画交给子元素。例如:
.text-container {
display: grid;
grid-template-rows: 1.2em auto;
}
.text-content {
overflow: hidden;
max-height: 1.2em; /* 收起 */
transition: max-height 0.3s ease;
}
.text-container.expanded .text-content {
max-height: 6em; /* 展开,值需 ≥ 最大可能高度 */
}
这里 max-height 是可动画的,且 grid 仍可用于对齐按钮、图标等其他元素。缺点是 max-height 必须设得足够大(否则展开被截),但比算 fr 轨道靠谱得多。
容易被忽略的兼容性与细节
grid-template-rows 动画在 Safari 16.4+ 才开始支持数值到数值的过渡(如 0px → 48px),旧版 Safari 和部分安卓 WebView 会直接跳变;而 max-height 方案兼容性好得多(IE10+)。另外:
- 行高计算要包含
padding和border,建议用box-sizing: border-box - 如果文本字体大小响应式变化(如
rem),用em比px更稳妥 -
visibility: hidden不能参与动画,别和height或max-height混用,否则动画中断 - 用
getComputedStyle(el).gridTemplateRows调试时,返回的是解析后字符串(如"1.2em 0px"),不是原始 CSS 值
真正卡住人的,往往不是怎么写,而是没意识到 fr 本质不可动画——这个前提错了,后面所有 transition 都白配。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











