Skip to content
⚠️ This article was written in 2019. Some content may be outdated.

CSS アニメーションパフォーマンス:原理から実践まで

CSS アニメーションはよく使われますが、書き方が悪いとカクついたり電池を消耗させたりします。アニメーション最適化の前に、ブラウザのレンダリングパイプラインを理解することが必要です。

ブラウザのレンダリングパイプライン

Style → Layout → Paint → Composite
  • Style:どの CSS ルールが適用されるかを計算
  • Layout(リフロー):幾何学(位置、サイズ)を計算
  • Paint:ピクセルを塗りつぶす(色、背景、影)
  • Composite:レイヤーをマージして画面に表示

Layout または Paint ステージのプロパティを変更するアニメーションは、毎フレーム高コストの処理をやり直します。transformopacity だけが Composite ステージで完全に処理されます。

プロパティがどのステージを引き起こすか

プロパティLayoutPaintComposite
width, height, margin
background, color
transform
opacity

アニメーションには可能な限り transformopacity を使いましょう。

left/top を transform に置き換える

css
/* 悪い例:毎フレームでレイアウト + ペイントを引き起こす */
@keyframes move-bad {
  from {
    left: 0;
  }
  to {
    left: 300px;
  }
}

/* 良い例:コンポジットのみ */
@keyframes move-good {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(300px);
  }
}

視覚的な結果は同じですが、transform バージョンは独立したコンポジットレイヤーで GPU 上で実行されます。

will-change:正しい使い方

will-change はアニメーション開始前に要素を独自のコンポジットレイヤーに昇格させるようブラウザに指示します:

css
.animated-menu {
  will-change: transform;
}
javascript
/* アニメーション完了後に削除する */
element.addEventListener("animationend", () => {
  element.style.willChange = "auto";
});

よくある間違い:

css
/* 間違い:すべてに追加しない */
* {
  will-change: transform; /* 何千ものコンポジットレイヤーを作成 */
}

will-change はアニメーション直前に適用し、完了後に削除すべきです。各コンポジットレイヤーは GPU メモリを消費します。

実践例:ドロップダウンメニュー

css
.dropdown {
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.2s ease;
  will-change: transform;
}

.dropdown.open {
  transform: scaleY(1);
}

このドロップダウンアニメーションは transform のみを使用します。毎フレームでのレイアウトやペイントはなく、完全に GPU アクセラレートされます。

MIT Licensed