transformプロパティを個別に指定

goran

@goran_nasai

こんにちは。GORAN です。今回はweb.dev の記事からインスパイアされた内容です。

transformプロパティ

transformは対象の要素に対して以下の操作を行うことができる CSS プロパティです。

  • 拡大縮小:scale
  • 回転:rotate
  • 傾斜:skew
  • 移動:translate
matrix は?

上記の操作を一括(行列)で操作できる関数。matrix3dのショートハンド。

記述例

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

個別指定

Chrome 104 において、上述の操作を個別に指定することが可能になりました。モダンブラウザ(Chrome・Firefox・Edge・Safari)では使えるようになったと判断して良いと思います。なぜか Chrome だけ遅れてたので、ようやくって感じでしょうか。

先ほどの記述は以下のように書き換えられます。

transformの個別指定
.target {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

実行順序

W3C の規定にあるようにtransformの処理のされ方は決まっていて、必ずtranslaterotatescaleの順に実行されます。 これは個別指定でも同様で、宣言された順番と実行される順序が一致しないケースがあります。 例えば以下のように記述しても先ほどの例と同じ結果が得られます。

transformの個別指定
.target {
  rotate: 30deg;
  translate: 50% 0;
  scale: 1.2;
}

何が嬉しいのか

記述量が減る

transformという記述をしなくて済むので「コードが短くなってよりわかりやすくなる」というのがあると思います。

@keyframesの記述は特に顕著で、これまでは

@keyframeのBEFORE
// prettier-ignore
@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;
}

だったのが以下のようになり、

@keyframeのAFTER
// prettier-ignore
@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;
}

機能分離ができて短くわかりやすくなります。

// prettier-ignoreは悪しからず)

アニメーションのパフォーマンス最適化

transitionwill-changeを使いたいケースです。

これまでは

transitionとwill-changeのBEFORE
.target-transition {
  transition: transform 0.4s;
}
.target-will-change {
  will-change: transform;
}

のように記述するしかなかったので、一部しか使わなくても一括の設定しかできなかったのですが、

transitionとwill-changeのAFTER
.target-transition {
  transition: translate 0.4s, rotate 0.2s;
}
.target-will-change {
  will-change: translate, rotate;
}

操作ごとの設定ができるようになりました。こちらの方がパフォーマンスに優れることもわかっています

表現の自由度

keyframesにしてもtransitionにしても、transformの操作を個別に指定できるようになったので、「translateは素早く、rotateはゆっくり」みたいなことが書けるようになりました。

おわりに

弊社ではなかなか「CSS アニメーションを最適化する」事案がないので、活躍の場は限られてますが、自社サービスなどパフォーマンスを拘れるプロダクトには積極的に適用していきたいですね。