使用 translate
、rotate
和 scale
属性转换元素
CSS transform
属性
如需对元素应用转换,请使用 CSS transform
属性。该属性接受一个或多个 <transform-function>
,这些 <transform-function>
会依次应用。
.target {
transform: translateX(50%) rotate(30deg) scale(1.2);
}
目标元素在 X 轴上平移了 50%,旋转了 30 度,最后放大到 120%。
虽然 transform
属性可以正常运行,但如果您想单独更改其中的任何值,就会变得有些繁琐。
如需更改悬停时的缩放比例,您必须复制 transform 属性中的所有函数,即使其值保持不变也是如此。
.target:hover {
transform: translateX(50%) rotate(30deg) scale(2); /* Only the value of scale() changed */
}
各个转换属性
随 Chrome 104 一起发布的是 CSS 转换的各个属性。这些属性分别是 scale
、rotate
和 translate
,您可以使用它们分别定义转换的各个部分。
这样一来,Chrome 就加入了 Firefox 和 Safari 的行列,这些浏览器已经支持这些属性。
使用各个属性重写前面的 transform
示例后,您的代码段将如下所示:
.target {
translate: 50% 0;
rotate: 30deg;
scale: 1.2;
}
顺序很重要
原始 CSS transform
属性与新属性之间的一个关键区别是声明的转换的应用顺序。
使用 transform
时,转换函数会按编写的顺序应用,即从左(外部)到右(内部)。
对于各个转换属性,顺序不是它们的声明顺序。顺序始终相同:先是 translate
(外部),然后是 rotate
,最后是 scale
(内部)。
这意味着以下两个代码段都会产生相同的结果:
.transform--individual {
translate: 50% 0;
rotate: 30deg;
scale: 1.2;
}
.transform--individual-alt {
rotate: 30deg;
translate: 50% 0;
scale: 1.2;
}
在这两种情况下,目标元素将首先沿 X 轴平移 50%
,然后旋转 30deg
,最后按 1.2
缩放。
如果将某个单独的转换属性与 transform
属性一起声明,则系统会先应用各个转换(translate
、rotate
和 scale
),最后应用 transform
(内部)。如需了解详情,请参阅定义应如何计算转换矩阵的规范。
动画
添加这些属性的主要原因是让动画更易于实现。假设您要为元素添加动画效果,如下所示:
使用 transform
如需使用 transform
实现此动画,您必须计算所有已定义的转换的所有中间值,并将这些值包含在每个关键帧中。例如,如需在 10% 处执行旋转,则必须计算其他转换的值,因为 transform
属性需要所有这些值。
生成的 CSS 代码如下所示:
@keyframes anim {
0% { transform: translateX(0%); }
5% { transform: translateX(5%) rotate(90deg) scale(1.2); }
10% { transform: translateX(10%) rotate(180deg) scale(1.2); }
90% { transform: translateX(90%) rotate(180deg) scale(1.2); }
95% { transform: translateX(95%) rotate(270deg) scale(1.2); }
100% { transform: translateX(100%) rotate(360deg); }
}
.target {
animation: anim 2s;
animation-fill-mode: forwards;
}
使用单独的转换属性
使用各个转换属性,编写起来会更容易。您可以单独定位到每个转换,而不是将所有转换从一个关键帧拖动到另一个关键帧。您也不再需要计算所有中间值。
@keyframes anim {
0% { translate: 0% 0; }
100% { translate: 100% 0; }
0%, 100% { scale: 1; }
5%, 95% { scale: 1.2; }
0% { rotate: 0deg; }
10%, 90% { rotate: 180deg; }
100% { rotate: 360deg; }
}
.target {
animation: anim 2s;
animation-fill-mode: forwards;
}
使用各个转换属性和多个关键帧
为了使代码模块化,您可以将每个子动画拆分为各自的一组关键帧。
@keyframes move {
0% { translate: 0% 0; }
100% { translate: 100% 0; }
}
@keyframes scale {
0%, 100% { scale: 1; }
5%, 95% { scale: 1.2; }
}
@keyframes rotate {
0% { rotate: 0deg; }
10%, 90% { rotate: 180deg; }
100% { rotate: 360deg; }
}
.target {
animation: move 2s, scale 2s, rotate 2s;
animation-fill-mode: forwards;
}
得益于这种拆分,您可以根据需要应用每组单独的关键帧,因为 transform
属性(现在已成为单独的属性)不再相互覆盖。除此之外,您还可以为每个转换设置不同的时间,而无需重写所有转换。
性能
使用这些新属性的动画的效率与现有 transform
属性的动画一样高。
translate
、rotate
和 scale
的动画在合成器上运行的方式与 transform
的动画相同,因此它们对动画性能的提升效果与 transform
一样。
这些新属性还可与 will-change
属性搭配使用。一般来说,最好避免过度使用 will-change
,只对所需元素的最低数量使用 will-change
,并且尽可能缩短使用时间。不过,尽可能具体说明问题也是有益的。例如,如果您使用 will-change
通过 rotate
和 filter
属性优化动画,则应使用 will-change: rotate, filter
进行声明。在为 rotate
和 filter
添加动画时,这种方法比使用 will-change: transform, filter
略胜一筹,因为 Chrome 在您使用 will-change
时预先创建的一些数据结构在 transform
和 rotate
之间有所不同。
“新近可互操作”系列的一部分