写完了八年 CSS,每次给列表加 View Transitions 都要写几百行命名——今天 view-transition-class 把这件事用三行彻底原生化了
写过 View Transitions 的人都知道这个痛:你有一百个产品卡片,每个都要有独立的 view-transition-name,CSS 里就要写 ::view-transition-group(card-1)、::view-transition-group(card-2)……写到第一百个。然后还要给 old/new/image-pair 各写一遍。三百行选择器,对应的动画逻辑其实一模一样。这不是代码,这是惩罚。
Chrome 125 引入的 view-transition-class 就是来解决这个问题的。它本质上是一个「分组钩子」,让多个有不同 view-transition-name 的元素共享同一套动画样式,而不需要给它们起一样的名字。
具体怎么用?每个元素照常给唯一的 view-transition-name,然后在样式表里加一行 view-transition-class:
.product-card {
view-transition-name: match-element;
view-transition-class: card;
}
这里 view-transition-name: match-element 是告诉浏览器「这个元素要参与过渡」,浏览器会自动给它生成一个唯一的名字。而 view-transition-class: card 是一个分组标签,可以重复——它不参与匹配,只参与样式。
然后三行替代三百行:
::view-transition-group(.card) {
animation-duration: 0.35s;
animation-timing-function: ease-out;
}
::view-transition-old(.card) {
object-fit: cover;
}
::view-transition-new(.card) {
animation: fadeIn 0.3s both;
}
注意这里 ::view-transition-group(.card) 里的 .card 是 view-transition-class 的值,不是 CSS class。它用点号语法,和普通 class 选择器类似,但只在这里有意义。所有 view-transition-class 值为 card 的元素,都会命中这三个规则——不管它们各自的 view-transition-name 是什么。
你还可以给同一个元素加多个 class:view-transition-class: card featured,这样 ::view-transition-group(.card) 和 ::view-transition-group(.featured) 都能命中它,适合大部分卡片用同一个动画、少数特色卡片换另一个动画的场景。
生产环境最爽的地方在哪里?你的样式表从此和列表长度彻底解耦。数据库有一百个产品,CSS 不变。变成一万个,CSS 还是那三行。以前用 Sass 循环生成选择器列表的团队,现在可以直接删掉那坨 build-time 代码。
需要注意的是:这个功能是添加性的,不影响已有的 view-transition-name 写法。如果浏览器不支持 view-transition-class,动画会走默认的 fade,效果不会坏,只是没有自定义时长而已。Chrome 125+ 和 Safari 18.2+ 已经支持,Firefox 还在路上,但渐进增强完全没问题。
三步下一步:第一步,把现在项目里所有 ::view-transition-group(card-N) 选择器列出来,看看能不能归类;第二步,给列表里的每个元素加上 view-transition-class;第三步,把那几百行选择器替换成 ::view-transition-group(.your-class) 三条规则,删掉生成选择器的 build step 代码。Scalable 的 View Transitions,从今天这三行开始。
view-transition-class 是 CSS View Transitions Module Level 2 的一部分,Baseline 2025,属于浏览器原生能力,不需要任何 polyfill。Firefox 支持后这套写法直接全量生效。
评论区
登录后可评论。