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

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

これらの推奨事項の背景にある理論については、アニメーションが遅いのはなぜですか?をご覧ください。

ブラウザの互換性

このガイドで推奨する CSS プロパティは、すべてブラウザ間の互換性が優れています。

transform

Browser Support

  • Chrome: 36.
  • Edge: 12.
  • Firefox: 16.
  • Safari: 9.

Source

opacity

Browser Support

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 2.

Source

will-change

Browser Support

  • Chrome: 36.
  • Edge: 79.
  • Firefox: 36.
  • Safari: 9.1.

Source

要素を移動する

要素を移動するには、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 をサポートしていないブラウザでレイヤの作成を強制するには、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 つの例でこれをテストし、DevTools を使用してパフォーマンスを調べることができます。

Chrome DevTools

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

[概要] タブの [レンダリング] に 0 以外の値が表示されている場合は、アニメーションによってブラウザがレイアウト作業を行っている可能性があります。

[概要] パネルには、レンダリングに 37 ミリ秒、ペイントに 79 ミリ秒と表示されています。
animation-with-top-left の例では、レンダリング作業が発生します。
[概要] パネルに、レンダリングとペイントの値がゼロと表示される。
animation-with-transform の例では、レンダリング作業は発生しません。

Firefox DevTools

Firefox DevTools のウォーターフォールを使用すると、ブラウザが時間を費やしている場所を把握できます。

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

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