Blog スタッフブログ

CSSアニメーションが遅くなる要因について

Webサイトでは、要素を回転させたり、スクロールに合わせて動かしたり、ふわっと表示させたりと、CSSを使ってさまざまなアニメーションを付けることができます。

こうした動きは、単体で使っている分には問題なく動いていても、複数のアニメーションを組み合わせることで、

「少し画面がカクつく」「スクロールが重く感じる」「スマートフォンだけ動きがぎこちない」

といった問題が起こる場合があります。

今回は、CSSアニメーションが重くなりやすい代表的なケースと、その理由を簡単に紹介します。

単体では問題なくても、組み合わせると重くなることがある

  • 背景画像をゆっくり動かす
  • アイコンを常に回転させる
  • スクロールに合わせて画像を拡大する
  • 要素をフェードインさせる
  • fixedで固定した要素を表示する

といった処理は、それぞれ単体で使う分には特に問題にならないことも多いです。

ただし、これらが同じ画面内で同時に動くと、ブラウザが一度にたくさんの描画処理を行うことになります。

その結果、パソコンやスマートフォンの性能によっては、画面の動きがカクつくことがあります。

transform を使っていても重くなる場合がある

transform: translate();
transform: scale();
transform: rotate();

といった transform を使うと比較的軽く動作するとされています。

ですが、大きな画像を複数動かしたり、画面全体に近いサイズの要素を常時アニメーションさせたりすると、それだけ描画する範囲が増えます。

特にスマートフォンでは、PCでは問題なかったアニメーションでも重く感じることがあります。

よくある組み合わせ

よくあるのが、ページのスクロール位置に合わせてアニメーションさせるケースです。

スクロール
↓
画像を移動
↓
画像を拡大
↓
別の要素をフェードイン

といった動きを同時に行う場合です。

スクロール中は、ユーザーが画面を動かすたびに表示内容を更新する必要があります。

そのタイミングで複数のアニメーションも同時に動かしていると、ブラウザ側の処理が増えます。

特にJavaScriptでスクロール位置を細かく取得しながらCSSを書き換えている場合は注意が必要です。

そこに、top や left で動かし続ける要素などが組み合わさるとレイアウトの再計算が発生するためより重くなります。

対策

画像の軽量化だけでは不十分な場合があります。

アニメーションを軽くする方法として、will-changeがあります。

will-change: transform;

これは、「この要素は今後transformが変化する」とブラウザに事前に伝えるためのCSSです。

うまく使えばアニメーションが滑らかになることがありますが注意点があります。

* {
  will-change: transform;
}

のようにとりあえず全部につけることをしてしまうと逆効果になってしまう場合があります。

基本的は動かすものだけにつける運用になります。

アニメーションを軽くするためのポイント

CSSアニメーションを使う際は、次のような点を意識すると安定しやすくなります。

  • 移動や拡大縮小はできるだけ transform を使う
  • フェードは opacity を使う
  • width、height、top、left の連続変更を避ける
  • 大きな画像を必要以上に動かさない
  • blurやshadowの多用を避ける
  • 同時に動くアニメーションの数を減らす
  • スクロールイベントの処理を増やしすぎない
  • will-change は必要な箇所だけに使用する