配了八年折叠动画,每次 height:0→auto 都要靠 JS 硬撑——今天 CSS 自己会了,interpolate-size 把这件事彻底原生化了
我配手风琴配了八年,每次展开收起都要靠 JS 套一层 max-height 才能勉强做动画——今天发现 CSS 自己会量了,interpolate-size: allow-keywords 把这件事彻底原生化了。
interpolate-size 是 Chrome 129 进入 Baseline 2024 的一个新属性,它的核心能力只有一个:允许 CSS 在「关键字尺寸」和「固定尺寸」之间做插值。什么叫关键字尺寸?height: auto、height: contain、width: min-content,这些都是浏览器自己算出来的值,传统上是不支持动画的。
举个例子。传统做折叠动画:
/* 效果是啥?没有动画,直接跳 */
.accordion-content {
height: 0;
overflow: hidden;
transition: height 0.3s;
}
.accordion-content.open {
height: auto; /* 浏览器:auto 怎么过渡?算不了,跳帧 */
}
这行 height: auto 放在 transition 后面,浏览器直接放弃治疗——auto 是多少它不知道,过渡动画自然做不了。
三行代码,彻底解决这个坑。
.accordion-content {
height: 0;
overflow: hidden;
interpolate-size: allow-keywords; /* 第一行:允许关键字尺寸参与插值 */
transition: height 0.3s, /* 高度本身过渡 */
visibility 0.3s; /* visibility 也配合过渡 */
transition-behavior: allow-discrete; /* 第三行:允许离散的属性(display/visibility)参与过渡 */
}
.accordion-content.open {
height: auto;
visibility: visible;
}
加上这三行之后,Chrome 129+ 浏览器就能把 height: 0 到 height: auto 之间的差值算出来,然后老老实实做动画了。
这是怎么工作的? 传统 transition 只支持数值到数值的插值(100px → 200px)。interpolate-size: allow-keywords 相当于给浏览器下了一个指令:「当遇到 auto、min-content、max-content 这些关键字时,自己去把它们的计算值算出来,然后参与插值。」浏览器会在动画开始前把目标尺寸预先算好,动画过程中实时插值,结束前再把真实值还原回去。
配合 @starting-style 做入场动画。 如果想在元素刚出现时也加一个从隐藏到显示的过渡,需要加上 @starting-style:
.accordion-content {
interpolate-size: allow-keywords;
transition: height 0.3s, visibility 0.3s;
transition-behavior: allow-discrete;
}
.accordion-content.open {
height: auto;
visibility: visible;
}
/* 元素刚显示时的初始样式,配合 @starting-style */
@starting-style {
.accordion-content.open {
height: 0;
}
}
配合 details/summary 做纯 HTML 手风琴。 如果你用的是原生 <details>/<summary> 组合,连 JS 都可以不要:
<details name="accordion">
<summary>第一项</summary>
<p>展开内容</p>
</details>
<details name="accordion">
<summary>第二项</summary>
<p>展开内容</p>
</details>
details {
interpolate-size: allow-keywords;
transition: height 0.3s, visibility 0.25s;
transition-behavior: allow-discrete;
}
details[open] {
height: auto;
visibility: visible;
}
/* exclusive 行为:一个打开另一个自动关闭 */
@starting-style details[open] {
height: 0;
}
加了 name=”accordion” 之后,<details> 会自动实现「同时只展开一个」的排他行为,这是原生支持的,不需要任何 JS。
兼容性现状。 interpolate-size: allow-keywords 目前只有 Chrome 129+ 支持,Firefox 和 Safari 还没上。生产环境使用时一定要加 @supports 渐进增强:
.accordion-content {
height: 0;
overflow: hidden;
}
@supports (interpolate-size: allow-keywords) {
.accordion-content {
interpolate-size: allow-keywords;
transition: height 0.3s, visibility 0.25s;
transition-behavior: allow-discrete;
}
.accordion-content.open {
height: auto;
visibility: visible;
}
}
不支持的浏览器会回退到没有动画的切换体验——这是可接受的降级方案。
下一步,你可以这样做。
- 把项目里所有套了 max-height hack 的手风琴组件找出来,换成这三行 CSS
- 如果你在用 React/Vue,手风琴的展开状态可以继续用状态管理,只需要把动画逻辑交给 CSS
- 在 caniuse.com 上关注 Firefox 和 Safari 的支持进度,一旦上 Baseline 2025,就可以全面推广
八年了,height: auto 的过渡动画终于不用再靠 JS 了。CSS 正在把那些「本来就应该浏览器自己会」的事情,一件一件还给我们。
评论区
登录后可评论。