對 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 的行列,這兩款瀏覽器已支援這些屬性。

瀏覽器支援

  • Chrome:104。
  • Edge:104。
  • Firefox:72。
  • Safari:14.1。

資料來源

使用個別屬性重寫上述 transform 範例,程式碼片段會變成這樣:

.target {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

順序很重要

原始 CSS transform 屬性和新屬性之間的一個主要差異,是宣告的轉換套用順序。

使用 transform 時,系統會依照函式寫入的順序套用轉換函式,也就是從左 (外側) 到右 (內側)。

個別轉換屬性中的順序並非宣告的順序。順序一律相同:先 translate (外部)、rotatescale (內部)。

也就是說,以下兩個程式碼片段會產生相同的結果:

.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 比使用 will-change: transform, filter 稍微好一些,因為 Chrome 在使用 will-change 時預先建立的部分資料結構,在 transformrotate 之間有所不同。

新互通系列