こんにちは!フロントエンド・アーキテクトの私です。
Webサイトを作っていて、「なんだかスマホでスクロールするとカクカクするな……」「アニメーションがイマイチなめらかじゃないな……」と頭を抱えた経験、ありませんか? 大丈夫です、あなただけじゃありません。世界中のエンジニアが一度は通る道ですからね。
今日は、この「カクつき」の正体を突き止め、ブラウザの裏側で何が起きているのかを一緒に覗いてみましょう。テーマは「GPUアクセラレーションと合成レイヤーの生成条件」です。
難しそうな漢字が並んでいますが、お買い物の流れや身近な道具に置き換えて優しくほどいていきますので、どうぞ肩の力を抜いてコーヒーでも飲みながら読んでいってください。
—
1. ブラウザが画面を表示する仕組みは「パラパラ漫画」
まず、ブラウザが私たちの目に映るWebページを描き出す仕組みをざっくりとお話ししますね。
ブラウザは、HTMLやCSSを読み込むと、頭の中で「こういうレイアウトにしよう」という設計図(DOMやCSSOM)を作ります。そして、それを画面というキャンバスにペンキで色を塗るように描き出していきます。
この作業、実はすべてパソコンやスマホの「CPU(頭脳)」が一生懸命やっています。
アニメーションするたびに、CPUが「はい、次のコマは文字を右にずらして、色は変えて……」と、何十枚もの絵を猛スピードで描き直しているんです。
でも、CPUってすごく忙しい子なんですよ。JavaScriptの計算をしたり、ネットワークの通信をさばいたり、大忙しです。だから、アニメーションが複雑になると手が回らなくなって、「うわー、追いつかない!」と息切れしてしまう。これが、スクロールやアニメーションがカクつく正体です。
そこで登場するのが、グラフィック専門のプロフェッショナル「GPU」の存在です。
—
2. 「合成レイヤー」ってなに? お絵描きボードの例え
ここで登場するのが今回の主役の一つ、「合成レイヤー(Composited Layers)」です。
イメージしてみてください。
一枚の大きなキャンバスにすべてを描き込もうとすると、一部分を動かすだけでもキャンバス全体を描き直さなきゃいけないから大変ですよね。
そこでブラウザは、「動かす予定のある部分」や「特別なパーツ」を、透明な下敷き(レイヤー)に切り分けて描くことを思いつきました。これが合成レイヤーです。
アニメのセル画を思い浮かべてください。
背景の絵はそのまま固定しておいて、キャラクターが描かれた透明なセル画だけをパラパラ動かせば、全部描き直さなくてもスルスル動かせますよね。ブラウザもこれと同じことをやっているんです。
そして、この透明な下敷きたちを最後にガッシャコと重ね合わせて1枚の画面にする魔法の作業を、GPUにお願いする。これが「GPUアクセラレーション」です。
—
3. どうすれば「合成レイヤー」は作られるのか?
「じゃあ、どうやったらその透明な下敷き(合成レイヤー)を作ってもらえるの?」という話ですよね。
ブラウザは基本的に、私たちが何も指定しないと「全部ひとつのキャンバス(メインのレイヤー)」で頑張ろうとします。しかし、特定のCSSを書くことで、ブラウザにこう囁くことができます。
> 「ねえ、この要素、あとですごく動かすから、今のうちに専用の下敷き(合成レイヤー)を切っておいてよ!」
その代表選手が、以下のプロパティたちです。
- `transform: translate3d(0, 0, 0);` や `transform: translateX(…)` などの3D/変形プロパティ
- `opacity` をアニメーションさせるとき
- そして、今回のもうひとつの主役である `will-change` プロパティ
`will-change` ってどんな魔法?
`will-change` は、ブラウザに対して「私、これからこの要素を変形させたり動かしたりする予定があるから、心づもりよろしくね!」と事前に予告(予約)するためのプロパティです。
例えば、ボタンにカーソルを合わせたときにフワッと持ち上がるようなリッチなアニメーションをさせたいとき、こう書きます。
.epic-button {
/ ブラウザに「この要素はあとでtransformが変わるよ」とこっそり教えてあげる /
will-change: transform;
transition: transform 0.3s ease;
}
.epic-button:hover {
transform: translateY(-5px);
}
これを指定しておくと、ブラウザは「なるほど、このボタン専用の下敷きをあらかじめ一枚用意しておこう」と判断し、GPU用のメモリを確保して待ち構えてくれます。いざホバーしたときには、CPUを煩わせず、GPUがその下敷きをスッと持ち上げるだけで済むので、それはもう滑らかな動きになります。
—
4. ちょっと待って! レイヤーを作りすぎると起きる「悲劇」
「おっ、じゃあ全部の要素に `will-change` を書けば、世界中のサイトが爆速になるんだな!」と思ったそこのあなた。
……残念ながら、世の中そんなに甘くありません(笑)。ここが実務で一番つまずきやすい罠なんです。
合成レイヤーを作るということは、「ブラウザ(GPU)専用のメモリ(VRAM)を余分に消費する」ということです。
透明な下敷きを何枚も、何百枚も机の上に広げたらどうなりますか?
机の上がごちゃごちゃになって、探すのも大変だし、何より机(メモリ)のスペースがすぐになくなってしまいますよね。
ブラウザのメモリが足りなくなると、スマホの動きが急に重くなったり、最悪の場合はブラウザがクラッシュして強制終了してしまいます。「良かれと思って書いたコードのせいで、ユーザーのスマホのバッテリーをゴリゴリ削って熱々にしてしまった……」なんていうのは、現場で本当によくある悲しい事故です。
優しいアドバイス:適材適所で使おう
- たくさんレイヤーを作っていい場所:
今まさにグリグリ動いているモーダルウィンドウ、スライダー、固定ヘッダー、複雑なアニメーション要素など。
- レイヤーを作っちゃいけない場所:
画面中にあるすべてのテキスト、ボタン、ただの背景画像など。「動かないかもしれないから一応……」と何でもかんでも `will-change` を貼るのは、お部屋に不要な段ボールを積み上げるようなものです。やめましょうね。
そして、アニメーションが終わったら、その予告(`will-change`)は外してあげるのが、優しくてスマートなフロントエンドエンジニアの作法です。
—
5. まとめ:ブラウザと仲良くなろう
いかがでしたでしょうか?
「GPUアクセラレーション」や「合成レイヤー」という言葉を聞くと、なんだか難しそうなエンジニアの要塞のように思えますよね。
でも、中身を紐解いてみれば、
1. 「全部をひとりでやるとCPUが疲れちゃうから、動かす部分だけ透明な下敷き(合成レイヤー)に分けよう」
2. 「その下敷きを動かす得意な担当(GPU)にお仕事をお願いしよう」
3. 「でも、下敷きを作りすぎるとメモリがパンクするから、ここぞという時にだけ使おう」
という、とってもシンプルな「お片付けの知恵」なんです。
Webブラウザは、私たちが書いたCSSの意図を一生懸命汲み取ろうと、裏側で必死に頭を働かせてくれています。仕組みを少しだけ知ってあげることで、ブラウザにとって居心地の良い、そしてユーザーにとって最高になめらかなWebサイトを作ることができるようになりますよ。
今日の帰り道、スマホでいろんなサイトをスクロールしながら、「あ、ここはレイヤーが分かれてサクサク動いてるな」なんてニヤリと想像してもらえたら、私としてもエンジニア冥利に尽きます。
それでは、また次の冒険でお会いしましょう!

コメント