こんにちは。田村です。
今回は「CSSアニメーションをより滑らかに動かすポイント」について、レンダリングの仕組みとGPUアクセラレーションの注意点を交えながらまとめてみました。
Webサイトでアニメーションを取り入れる場合、プロパティの選び方やGPUの活用次第でパフォーマンスが大きく変わります。
それでは早速、ブラウザのレンダリング工程から見ていきましょう。
CSSレンダリングの概要
ざっくりレンダリングの流れ
ブラウザは、HTML/CSS/JavaScriptを解析してまず DOMツリー と CSSOMツリー を生成します。
その後、この2つを合体させた Render Tree を作り、以下の手順で画面に描画します。
Rendering(レンダリング)
Layout(レイアウト)
各要素の大きさや位置を計算する工程。一般的に「リフロー」とも呼ばれます。
Painting(ペインティング)
Paint(ペイント)
テキストや背景色、ボーダー、画像などを ピクセル情報 として実際に塗りつぶす工程。
Composite Layer (コンポジットレイヤー)
レイヤーごとにGPUで合成し、最終的な見た目を描画する工程。
アニメーションを滑らかにする際に重要なのは、GPUアクセラレーションは主にComposite Layerで働くということです。
要素をうまく使うと、レイアウトの再計算(リフロー)を発生させずにCompositeだけでアニメーションできるため、滑らかな動作が期待できます。
GPUアクセラレーションが働く代表的なプロパティ
- will-changeプロパティの使用
- transformの3D変換
- opacityの変更
- position: fixedの要素
CSS のパフォーマンス最適化 - ウェブ開発を学ぶ | MDN
MDN Web Docs
スタイル設定されていないページを描画し、スタイルが解釈できたら再描画するというのは、ユーザーにとって使い勝手が悪いものです。このため、CSS は、ブラウザーがその CSS が現在必要でな...
transform
transform: translate(), scale(), rotate(), skew() などは、Layoutに影響しない ため、要素の大きさ・位置、レイアウトの再計算(リフロー)を必要としません。
opacity
opacityの変更は、レイアウト計算(幅や高さの再計算)には影響しないため、通常はLayoutやPaintを変えずにComposite Layerだけで変化を適用できます。
そのため、opacityのフェードアニメーションは比較的スムーズに動作します。
ただし、opacity は背景や重なり合いが複雑な場合paint処理が増える場合もあるので、必ずしも高速とは限りません。
CPUレンダリングとGPUレンダリングの違い
CPU側での処理
top や left, width, height などのプロパティをアニメーションさせると、毎フレームごとにレイアウトの再計算(リフロー)が発生します。
複数要素で同時にこうしたアニメーションを使うとCPUに大きな負担がかかり、カクつきの原因になります。
GPU側での処理
GPUは 2D/3Dの描画や合成 に特化しており、並列処理が得意です。
transform や opacity でアニメーションする場合は、新たなレイアウト計算をせずにComposite Layerのみで見た目を更新できるため、フレームレート(60fps)を維持しやすいというメリットがあります。
アニメーションのパフォーマンスとフレームレート - ウェブパフォーマンス | MDN
MDN Web Docs
ウェブ上でのアニメーションは、SVG、JavaScript( や WebGL を含む)、CSS の animation、、アニメーション GIF、さらにアニメーション PNG やその他の種類の画像もあります。CSS プロパテ...
任意でGPUアクセラレーションを引き出す方法
will-changeプロパティ
ブラウザに「もうすぐこのプロパティが変化するぞ」と知らせることができるので、あらかじめ最適化しておいてくれます。
ですが、ブラウザはすでに可能な限りすべての最適化を試みていますので指定しすぎると不要なレイヤーが生成されるため、使用には注意が必要です。
.element { will-change: transform, opacity; }
will-change - CSS: カスケーディングスタイルシート | MDN
MDN Web Docs
CSS の will-change プロパティは、どのような要素の変更が予測されているかブラウザーに助言します。ブラウザーは要素が実際に変更される前に、最適化をセットアップすることができます。こ...
GPU処理に良いケース
複数要素を同時にアニメーションさせる場合
画像ギャラリーが横に大量に流れるサイトなどは、レイアウトの再計算(リフロー)を最小限に抑え、滑らかな移動がしやすい。
スクロール連動やドラッグ移動など、ユーザー操作が頻繁に行われるUI
リアルタイムで要素位置が変化する場合に効果を発揮しやすい。
端末の性能が低い、またはFPSを確保したい場面
スマートフォンやタブレットなどCPUリソースが限られる環境で、GPUをフル活用することでカクつきを低減できる。
GPU処理の注意点
レイヤーが増えすぎた場合
レイヤーが増えすぎるとGPUのメモリ消費が増大し、合成コストもかさんで逆効果になる場合がある。
レイアウト変更時
transform や opacity はあくまで見た目を変えるプロパティなので、要素の実際の位置・高さを変えたい場合はレイアウトの再計算(リフロー)が発生する。
ブラウザ依存
古い端末や特定ブラウザではGPUの最適化が効きにくい。
メインスレッドの負荷は別問題
JavaScriptが重い処理を実行していれば、アニメーションの更新タイミング自体が遅れ、カクつきが発生することもある。
実測・検証方法
最終的には実際に パフォーマンス計測 してみることが大切です。
Chrome DevToolsのレンダリングを活用する
Chrome DevToolsのRenderingタブを活用しよう | フロントエンドBlog | ミツエーリンクス
フロントエンドBlog
Chrome DevToolsにはさまざまな機能が搭載されています。そのうちの1つ「Rendering」には、ページのレンダリングパフォーマンスを視覚化する機能や、さまざまな見え方を疑似的に再現する機能...
まとめ
transform や opacity を中心にアニメーションを組み立て、なるべくレイアウトの再計算(リフロー)を防ぎ、GPUアクセラレーションを効かせるのが、CSSアニメーションを滑らかに動かすポイントです。
やみくもにwill-changeを使うとレイヤーが乱立し、逆効果になることもありますので、Chrome DevToolsで実際に計測し、Paint/Compositeをチェックしながら、GPU処理が必要な箇所に使用すると良いでしょう。
より滑らかなアニメーションを実装してみてください!
告知
2025年1月31日(金)21:00~29:00 開催の「#朝までマークアップ 2(CSS編)」に出演いたします。
当日は、CSS アニメーションに関するお話をします。この記事にご興味を持っていただけましたら、ぜひご参加ください!
CSS Nite
2025-01-31(金)21:00 - 2025-02-01(土)05:00 2023年11月に開催した#朝までマークアップ、今回はCSS特集で開催します。23組24名の猛者が持ち時間10分、合計8時間のボリュームでお届けしま...
関連するタグ
全 1 件中 1 〜 1 件目を表示
この記事を書いた人
たむら しょうご
HTML&CSSコーダー
ウェブアクセシビリティ対応、フロントエンド開発、CMSを利用したウェブサイト制作を担当しています。
趣味はガーデニングです。