通过单独的转换属性对 CSS 转换进行更精细的控制

转换具有 translaterotatescale 属性的元素

CSS transform 属性

如需对元素应用转换,请使用 CSS transform 属性。该属性接受一个或多个接一个应用的 <transform-function>

.target {
  transform: translateX(50%) rotate(30deg) scale(1.2);
}

目标元素在 X 轴上平移 50%,旋转 30 度,并最终放大到 120%。

虽然 transform 属性可以正常运行,但当您需要单独更改其中的任何值时,它就会变得有点繁琐。

若要更改悬停时的缩放比例,您必须复制转换属性中的所有函数,即使它们的值保持不变。

.target:hover {
  transform: translateX(50%) rotate(30deg) scale(2); /* Only the value of scale() changed */
}

各个转换属性

Chrome 104 中装载的是 CSS 转换的各个属性。属性包括 scalerotatetranslate,可用于单独定义转换的这些部分。

这样,Chrome 浏览器将加入已支持这些属性的 Firefox 和 Safari。

浏览器支持

  • 104
  • 104
  • 72
  • 14.1

来源

使用单个属性重写上面的 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 属性一起声明,则先应用各个转换(translaterotate,然后是 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 属性的动画一样高效。

translaterotatescale 的动画在合成器上运行的方式与 transform 的动画相同,因此它们有利于提升动画性能,transform 相同

这些新属性也适用于 will-change 属性。一般来说,最好避免过度使用 will-change,方法是针对最少数量的元素使用它,并尽可能缩短使用时间。但最好尽量具体。例如,如果您使用 will-change 通过 rotatefilter 属性优化动画,则应使用 will-change: rotate, filter 进行声明。如果您要为 rotatefilter 添加动画效果,那么这比使用 will-change: transform, filter 稍好一点,因为当您使用 will-change 时,Chrome 提前创建的某些数据结构对于 transformrotate 有所不同。

全新可互操作系列课程的一部分