高性能な CSS アニメーションを作成する方法

このガイドでは、高パフォーマンスの CSS アニメーションを作成する方法について説明します。

これらの推奨事項の背後にある理論については、一部のアニメーションの動作が遅い理由をご覧ください。

ブラウザの互換性

このガイドで推奨するすべての CSS プロパティは、クロスブラウザを適切にサポートしています。

transform

対応ブラウザ

  • 36
  • 12
  • 16
  • 9

ソース

opacity

対応ブラウザ

  • 1
  • 12
  • 1
  • 2

ソース

will-change

対応ブラウザ

  • 36
  • 79
  • 36
  • 9.1

ソース

要素を移動する

要素を移動するには、transform プロパティの translate または rotation キーワード値を使用します。

たとえば、ビュー内にアイテムをスライドして表示するには、translate を使用します。

.animate {
  animation: slide-in 0.7s both;
}

@keyframes slide-in {
  0% {
    transform: translateY(-1000px);
  }
  100% {
    transform: translateY(0);
  }
}

要素を回転するには、rotate を使用します。次の例では、要素を 360 度回転させます。

.animate {
  animation: rotate 0.7s ease-in-out both;
}

@keyframes rotate {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}

要素のサイズを変更する

要素のサイズを変更するには、transform プロパティの scale キーワード値を使用します。

.animate {
  animation: scale 1.5s both;
}

@keyframes scale {
  50% {
    transform: scale(0.5);
  }
  100% {
    transform: scale(1);
  }
}

要素の公開設定を変更する

要素の表示と非表示を切り替えるには、opacity を使用します。

.animate {
  animation: opacity 2.5s both;
}

@keyframes opacity {
  0% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

レイアウトまたはペイントをトリガーするプロパティを避ける

アニメーションに CSS プロパティ(transformopacity 以外)を使用する前に、プロパティがレンダリング パイプラインに与える影響を確認してください。どうしても必要な場合を除き、レイアウトやペイントをトリガーするプロパティは使用しないでください。

レイヤ作成の強制

一部のアニメーションが遅いのはなぜですか?で説明したように、要素を新しいレイヤに配置すると、ブラウザはレイアウトの残りの部分を再描画することなく要素を再描画できます。

ブラウザは通常、どのアイテムを新しいレイヤに配置するかを適切に判断できますが、will-change プロパティを使用して手動でレイヤを強制的に作成することもできます。このプロパティは、名前が示すように、この要素がなんらかの方法で変更されることをブラウザに伝えます。

CSS では、任意のセレクタに will-change を適用できます。

body > .sidebar {
  will-change: transform;
}

ただし、仕様では、これは常に変更される可能性のある要素に対してのみ行う必要があることが推奨されています。たとえば、ユーザーがスライドイン / スライドアウトできるサイドバーなどが該当します。頻繁には変更されない要素で、変更が発生する可能性がある場合は、JavaScript を使用して will-change を適用することをおすすめします。ブラウザが必要な最適化を行うのに十分な時間を確保し、変更が停止したらプロパティを削除します。

will-change をサポートしていないブラウザ(多くの場合 Internet Explorer)でレイヤ作成を強制する場合は、transform: translateZ(0) を設定できます。

遅いアニメーションや不具合のあるアニメーションをデバッグする

Chrome DevTools と Firefox DevTools には、アニメーションの動作が遅い理由や不具合の原因を特定するために役立つさまざまなツールがあります。

アニメーションがレイアウトをトリガーするかどうかを確認する

transform 以外を使用して要素を移動するアニメーションは、動作が遅くなる可能性があります。次の例では、transform を使用したアニメーションと、topleft を使用したアニメーションを比較しています。

すべきでないこと
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     top: calc(90vh - 160px);
     left: calc(90vw - 200px);
  }
}
推奨事項
.box {
  position: absolute;
  top: 10px;
  left: 10px;
  animation: move 3s ease infinite;
}

@keyframes move {
  50% {
     transform: translate(calc(90vw - 200px), calc(90vh - 160px));
  }
}

次の 2 つの Glitch の例でこれをテストし、DevTools を使用してパフォーマンスを確認できます。

Chrome DevTools

  1. [パフォーマンス] パネルを開きます。
  2. アニメーションの実行中に、ランタイム パフォーマンスを記録します。
  3. [概要] タブを調べます。

[Summary] タブの [Rendering] にゼロ以外の値が表示される場合は、アニメーションによってブラウザがレイアウトを機能させている可能性があります。

[Summary] パネルには、レンダリングに 37 ms、ペイントに 79 ms と表示されます。
animation-with-top-leftの例では、レンダリング処理が発生します。
[Summary] パネルに、レンダリングとペイントの値が 0 と表示されます。
animation-with-transform サンプルでは、レンダリング処理は行われません。

Firefox DevTools

Firefox DevTools では、ウォーターフォールを使用して、ブラウザがどこで処理に時間がかかっているかを把握できます。

  1. [パフォーマンス] パネルを開きます。
  2. アニメーションの進行中にパフォーマンスの記録を開始します。
  3. 記録を停止し、[Waterfall] タブを調べます。

[Recalculate Style] のエントリが表示された場合、ブラウザはレンダリング ウォーターフォールの先頭に戻ってアニメーションをレンダリングする必要があります。

フレーム落ちがないか確認する

  1. Chrome DevTools で [レンダリング] タブを開きます。
  2. [FPS メーター] チェックボックスをオンにします。
  3. アニメーションの実行中に値を監視します。

FPS メーター UI の上部にある [フレーム] ラベルに注意してください。50% 1 (938 m) dropped of 1878 などの値が表示されます。高パフォーマンスのアニメーションは、99% のように高い割合を持ちます。これは、ドロップされるフレームが少なく、アニメーションが滑らかに見えることを意味します。

FPS メーターでフレームの 50% がドロップされたと表示される
animation-with-top-leftの例では、フレームの 50% がドロップされます
FPS メーターで 1% のフレームしかドロップされない
animation-with-transform の例では、フレームの 1% のみがドロップされます。

アニメーションがペイントをトリガーするかどうかを確認する

一部のプロパティは、他のプロパティよりもブラウザでのペイントのコストが高くなります。たとえば、ぼかし(影など)を含むものは、赤いボックスを描画するよりもペイントに時間がかかります。このような違いは、CSS では必ずしも明らかではありませんが、ブラウザの DevTools を使用すると、再ペイントが必要な領域や、その他のペイント関連のパフォーマンスの問題を特定できます。

Chrome DevTools

  1. Chrome DevTools で [レンダリング] タブを開きます。
  2. [ペイント フラッシュ] を選択します。
  3. 画面上でポインタを移動します。
再描画されることを示すため緑色でハイライト表示された UI 要素
Google マップのこのサンプルでは、要素が再ペイントされています。

画面全体が点滅する、または変更するべきではない領域がハイライト表示される場合は、さらに調査してください。

特定のプロパティがペイント関連のパフォーマンス問題を引き起こしているかどうかを判断する必要がある場合は、Chrome DevTools のペイント プロファイラが役立ちます。

Firefox DevTools

  1. [設定] を開き、ペイント点滅の切り替えのツールボックス ボタンを追加します。
  2. 検査するページでボタンをオンにし、マウスを動かすかスクロールすると、ハイライト表示された領域が表示されます。

おわりに

可能であれば、アニメーションを opacitytransform に制限して、レンダリング パスの合成ステージにアニメーションを残します。DevTools を使用して、パスのどのステージがアニメーションの影響を受けるかを確認します。

ペイント プロファイラを使用して、特にコストの高いペイント オペレーションがあるかどうかを確認します。問題が見つかった場合は、別の CSS プロパティを使用することでデザインが同じになり、パフォーマンスが向上しているかどうかを確認します。

will-change プロパティは、パフォーマンスの問題が発生した場合にのみ、慎重に使用してください。