變形的秩序(CSS transform order matters)

懶人包

事物的秩序1

你知道嗎,CSS transform 的順序會影響元件的變形結果。

比如以下借自 MDN 的 CSS class 樣式,將其套用到 div 元件後,會發現.one.two 的變形結果不同:

.one {
  transform: translateX(200px) rotate(135deg);
}
.two {
  transform: rotate(135deg) translateX(200px);
}

See the Pen transform order matter by Charlie (@Charlie7779) on CodePen.

為什麼?因為執行變形時,會將 transformation functions (即 translateX() / rotate() 等)轉為矩陣,並從左側一路往右乘。但因為矩陣乘法並不符合交換律,所以變形的順序會影響結果。

如果我就是不想在乎順序呢?

😠:我只是來切版的,不要跟我講數學,就沒有不管順序的方法嗎?

🦊:還真的有。大部分的瀏覽器現在都支援「直接指定 rotate/scale/translate 的值來進行變形」。所以上方範例可以改寫為:

.one {
  translate: 200px 0;
  rotate: 135deg;
}

.two {
  rotate: 135deg;
  translate: 200px 0;
}

然後你會發現現在兩個 div 的變形結果一樣了 🌹:

See the Pen I want to get rid of transform order by Charlie (@Charlie7779) on CodePen.

為什麼順序有差——CSS Transforms Module Level 1 規格陪讀

首先 CSS Transforms Module Level 1 第三節與第八節是這樣寫的:

3. The transform Property: The final transformation value for a coordinate system is obtained by converting each function in the list to its corresponding matrix like defined in Mathematical Description of Transform Functions, then multiplying the matrices.

8. The Transform Function Lists: The resulting transform is the matrix multiplication of the list of transforms.

變形結果是「根據每一個 transform function 的矩陣相乘後」得出來的。而每一個 transform function 的矩陣型態要去看 12. Mathematical Description of Transform Functions。比如 translate() 的矩陣長這樣:

CSS transform function "translate" in matrix format

rotate() 的長這樣:

CSS transform function "rotate" in matrix format

最後,把本篇文章一開始的舉例抓回來。transform: translateX(200px) rotate(135deg); 轉成矩陣並相乘後的結果是:

math result of "first translateX, then rotate"

transform: rotate(135deg) translateX(200px); 轉成矩陣並相乘後的結果是:

math result of "first rotate, then translateX"

兩種 CSS class 樣式最終得出的乘積不同,確認 transform function 的順序會影響變形結果。

參考文獻

註解

  1. 我無法放過致敬傅柯的任何機會 🌚