ブラウザの「レイヤー」を制する者は、60fpsを制する:コンポジットの深淵へようこそ
やあ。現場でバリバリコードを書いている君なら、一度は「ブラウザの描画が重い」という壁にぶつかったことがあるはずだ。アニメーションがカクつく、スクロールが引っかかる。そんな時、多くのエンジニアはとりあえず `will-change: transform` をおまじないのように書く。
だが、なぜそれが効くのか、そしてなぜ乱用してはいけないのか。今日は、ブラウザが裏側で必死に行っている「コンポジット(合成)」の仕組みを解剖しよう。ここを理解すれば、君のフロントエンドエンジニアとしての解像度は一段階上のレベルに引き上がるはずだ。
—
ブラウザが「レイヤー」を切る理由:全体を描き直すなんて無駄の極み
ブラウザのレンダリングエンジン(BlinkやWebKit)は、DOMとCSSOMを組み合わせて「レンダーツリー」を作り、レイアウトを計算し、ペイントを行う。ここまでは基本だ。
しかし、もし画面上で小さなボタン一つがホバーで色を変えるたびに、画面全体のピクセルを再計算してGPUに送っていたらどうなるか?想像するだけで恐ろしい。CPUとGPUの間のバスがパンクする。
そこで登場するのが「コンポジット・レイヤー」だ。
ブラウザは特定の条件を満たした要素を、メインの描画エリアから「切り離して別レイヤー」にする。このレイヤーは個別にGPUにアップロードされる。すると、要素が動いたり変化したりしたとき、ブラウザは「そのレイヤーだけを動かせばいい」と判断できる。これが、Webが滑らかに動くための最大の秘密だ。
合成レイヤー(Composited Layer)が生成される条件
ブラウザが「こいつは独立させたほうが効率がいいな」と判断する主なトリガーは以下の通りだ。
1. 3D変換や特定のCSSフィルタ: `transform: translateZ(0)` や `filter: blur()` など。
2. `will-change` プロパティ: 明示的に「こいつは今後変わるぞ」とブラウザにヒントを与える。
3. ビデオやCanvas要素: これらはハードウェアアクセラレーションとの相性が非常に良い。
4. `position: fixed` や `sticky`: 特定の条件下で独立レイヤー化されることが多い。
ただし、「レイヤーを作りすぎるとメモリを食いつぶす」という落とし穴がある。レイヤーはGPUのVRAMを消費する。スマホのようなメモリ制約の厳しいデバイスでレイヤーを乱造すれば、ブラウザはメモリ不足でタブを強制終了させるだろう。
—
実践:レイヤーを最適化するコードの書き方
理屈はわかった。では、どう書くのがベストか。
まずは、Chrome DevToolsの「Layers」パネルを開いてほしい。今君が作っているUIが、どうレイヤー分割されているかが一目瞭然だ。
以下は、パフォーマンスを意識した「滑らかなモーダルアニメーション」の実装例だ。
/
- 良い例: 必要な時だけレイヤーを昇格させる
- .is-active がついた瞬間だけ GPU に最適化させることで
- メモリ消費を最小限に抑えつつ、アニメーションを滑らかにする
/
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
/ 初期状態ではレイヤーを分けず、メモリを節約 /
will-change: auto;
transition: transform 0.3s ease;
transform: translateY(100%);
}
.modal.is-active {
/ アニメーション開始時にレイヤーを昇格させる /
will-change: transform;
}
/
- 悪い例:
- すべての要素に will-change を書くと、
- 数十〜数百のレイヤーが生成され、メモリが枯渇して
- 逆にスクロールがカクつく原因になる。
/
.card-item {
will-change: transform; / これを全リスト項目に書くのはNG! /
}
チーフアーキテクトからの助言:見えない負荷を可視化せよ
現場で「なぜか遅い」というバグに遭遇したとき、君が最初に見るべきはコードではなく、Chrome DevToolsの「Rendering」タブだ。
- Layer Borders: レイヤーの境界を可視化する。オレンジや緑の枠線が出てくるはずだ。これが多すぎないか確認しよう。
- Paint Flashing: どこが再描画(ペイント)されているかを緑色でハイライトする。アニメーション中に画面全体が緑色に光るなら、それはレイヤー化がうまくいっていない証拠だ。
まとめ:魔法はない、あるのは構造のみ
ブラウザは魔法使いではない。我々が書いたCSSを、CPUとGPUの限界ギリギリのバランスで解釈しているに過ぎない。
1. レイヤーは「必要な時だけ」作る: `will-change` は最強の武器だが、使いすぎると自爆する。
2. GPUへの負荷を意識する: ブラウザの合成プロセスは魔法ではなく計算だ。
3. 計測を怠るな: DevToolsの「Layers」と「Rendering」タブは、君にとってのレントゲン写真だ。
フロントエンドの最適化とは、ブラウザの「心」を読んで、いかに余計な仕事をさせないかというゲームなんだ。ぜひ、次のプルリクエストでこの視点を取り入れてみてくれ。きっと、UIの滑らかさが一段階変わるはずだ。
また何か壁にぶつかったら、いつでも聞きに来るといい。現場からは以上だ。

コメント