CSSGrid的`fr`单位在动画中无法平滑过渡,因为`grid-template-rows`属性不可动画,且`fr`作为弹性份额无法插值。替代方案是使用`max-height`配合过渡,或通过`transform:scaleY()`实现平滑显隐效果。
先说几个核心判断:grid-template-rows 里用 0fr → 1fr 做过渡,说它“不自然”都是客气的——实际上,它根本就不会动。浏览器直接跳变,没有中间帧,就是那么干脆。

长期稳定更新的攒劲资源: >>>点此立即查看<<<
用 grid-template-rows 做动画,本身就是个误区。因为它压根儿就不是可动画的属性。
grid-template-rows 本身不可动画W3C的规范里写得明明白白,grid-template-rows 和 grid-template-columns 都是 not animatable。哪怕你写了 transition: grid-template-rows 0.3s,浏览器也只会当作没看见,执行完就立刻重新布局,不会有任何过渡效果。
不少同学碰到过类似的情况:
element.style.gridTemplateRows,也看不到缓动效果;overflow: hidden,加上内容高度本来就小,造成的视觉错觉。为什么 fr 单位没法插值?因为 fr 不是像素,它是个“弹性份额”,代表的是剩余空间的份额。它的实际像素值,取决于父容器宽高、字体大小、滚动条是否存在,甚至其他轨道的尺寸。浏览器在动画的每一帧里,都没法确定当前 fr 值该对应多少像素——没有确定的路径,自然没法插值。
max-height 过渡比 fr 更可靠真正能平滑过渡的,是数值型、可插值的属性,比如 max-height、transform、opacity 这些。
用 max-height 做过渡,有几个关键约束需要注意:
max-height: 0,不能用 none 或 fit-content;max-height: 400px;overflow: hidden,否则内容溢出会破坏动画效果;getBoundingClientRect().height 再写入,但这样会失去纯 CSS 的简洁性。来看一个典型的示例结构:
.accordion-panel {
max-height: 0;
overflow: hidden;
transition: max-height 0.25s ease, opacity 0.25s ease;
}
.accordion-panel.is-open {
max-height: 400px;
opacity: 1;
}
transform: scaleY() 是更稳的替代方案对单个网格项做缩放,比动整个轨道要轻量得多,也更可控。而且,所有现代浏览器都支持 transition: transform。
实操的时候,有几个要点:
height 或 min-height,然后用 transform: scaleY() 来控制显隐;transform: scaleY(0) + transform-origin: top;transform: scaleY(1);scaleY(0) 完全隐藏时触发文字重排,可以同步加上 opacity: 0 控制。不过它有个小问题:它不改变文档流,所以热区和点击区域仍然按原始尺寸来响应。必要时,需要配合 pointer-events: none 或者用伪元素来补足。
说到底,fr 单位天生就不适合做动画。这不是 bug,是它设计上的局限。想让 Grid 区域“动起来”,就得把动画的压力从轨道定义转移到子元素自身——要么靠 max-height 模拟高度变化,要么靠 transform 做视觉缩放。硬着头皮跟 grid-template-rows 较劲,只会反复踩进重排的陷阱里。
侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述