こんにちは!Webフロントエンドの世界へようこそ。チーフアーキテクトの私です。
いきなりですが、あなたが日々情熱を込めて書いているHTMLやCSS。ブラウザは一体裏側で、どんな魔法を使って画面に表示しているか気になりませんか? 「コードを書いたら勝手にきれいに並んで表示される」――そう思っていた時期が、私にもありました。
でも実は、ブラウザの中では「ものすごい大工仕事」が毎秒のように繰り広げられているんです。そして、その大工仕事をちょっとサボらせてしまう(無駄働きさせる)と、ユーザーがスマホでスクロールしたときに「カクカク……」と重い動作になってしまいます。
今回は、その大工仕事の最難関であり、パフォーマンス低下の元凶になりがちな「レイアウト(リフロー)」の正体に迫ります。難しい専門用語はなるべく身近な例えに置き換えて優しく解説しますので、コーヒーでも飲みながら、リラックスして読んでいってくださいね。大丈夫、一緒に紐解けば絶対に理解できますよ!
—
1. ブラウザの中の大工さん:DOMからレンダーツリーができるまで
まず、ブラウザが画面を表示するまでの流れを、大きなおもちゃのブロック作りに例えてみましょう。
1. HTMLの解析(パース):
ブラウザがサーバーからHTMLを受け取ると、「ここに青いパーツがあって、その中に赤いパーツがあって……」と、部品の設計図を上から順に読み解いていきます。これがDOMツリーの構築です。いわば、家の中にあるすべての家具のリストアップですね。
2. CSSの解析(パース):
同時に、CSSも読み込みます。「青いパーツは幅100px、赤いパーツは文字を太く」といった、お化粧やスタイルのルールです。これがCSSOMツリーです。
3. レンダーツリーの合体:
「どのパーツに、どんな見た目のルールを適用するか」を合体させます。これがレンダーツリーです。
さあ、ここからが本番です。
「このパーツは画面のどこに置けばいいんだっけ?」「他のパーツと重なっていない?」という、『位置と大きさの計算』をしなければなりません。
この、画面上の正確な座標や大きさを計算する作業こそが、今回主役として取り上げる「レイアウト(ブラウザのエンジンによってはリフローとも呼ばれます)」なのです。
—
2. レイアウト(リフロー)って、身近な何に例えられる?
レイアウトのイメージをつかむために、「リビングの家具の模様替え」を想像してください。
あなたは今、リビングに新しい大きなソファを買いました。
「このソファを置くなら、テレビ台を右に50cmずらして、それに合わせてラグの位置も直して、あ、そうすると本棚の扉が開かなくなるから本棚も動かさなきゃ……!」
……たった一つのソファ(要素)の位置を変えただけなのに、部屋全体の家具の位置やサイズを連鎖的に計算し直す必要がありますよね。これが、Webブラウザで起きている「レイアウト(リフロー)」です。
再計算の連鎖が重い理由
Webページは、上から下へ、右から左へ、お互いに影響し合ってレイアウトが決まっています。そのため、たったひとつのボタンの幅を「1px広げた」だけでも、ブラウザは「うわっ、隣の要素も押し出される! その下の段落も下がらなきゃ!」と、ページ全体の計算をやり直すハメになるのです。これが、ブラウザにとってもの凄く重労働な理由です。
—
3. 要注意!レイアウトを誘発してしまう代表的なプロパティたち
では、どんなときにブラウザはこの「大がかりな模様替え(レイアウト)」を始めてしまうのでしょうか?
実は、CSSのプロパティには「触るとレイアウトが起きるもの」と「起きないもの」があります。レイアウトを引き起こしてしまう主な代表選手たちを見てみましょう。
- 大きさに関するもの:`width`, `height`, `padding`, `margin`, `border`
- 位置に関するもの:`top`, `bottom`, `left`, `right` (positionがstatic以外のとき)
- レイアウトの骨組みに関するもの:`display: flex`, `display: grid` の設定変更や、文字サイズを変える `font-size` など
「あれ、これって普段のコーディングでめちゃくちゃ使うプロパティばかりじゃん……!」と思いましたか?
はい、その通りです。これらを使わないWebサイトを作ることは不可能です。
だからこそ、「やみくもに何回もレイアウトを発生させない工夫」がプロの腕の見せ所になるわけですね。
—
4. やっちゃいけない!パフォーマンスを殺す「レイアウトの罠」
ここで、初心者の方がやりがちな、ブラウザを泣かせる悪夢のようなコードの書き方をご紹介します。
JavaScriptを使って、ループ処理の中で要素の大きさを変えたり、位置を読み取ったりするコードです。
// ❌ やってはいけないアンチパターン(強制同期レイアウトの罠)
const box = document.getElementById(‘my-box’);
for (let i = 0; i < 100; i++) { // 1. 幅を変更する(レイアウトのタスクが予約される) box.style.width = i + 'px'; // 2. 「今の幅はいくつ?」とブラウザにすぐ聞き返す // ブラウザ「えっ、今幅変えたばかりだから、慌てて計算し直さなきゃ!(強制レイアウト)」 console.log(box.offsetWidth); } このコードを実行すると、ブラウザは「変える→計算する→答える」を100回も繰り返します。 これをプログラミングの世界で「レイアウトスラッシング(レイアウトの暴風雨)」と呼びます。ブラウザが悲鳴を上げ、画面がカクつく原因ナンバーワンです。
でも、安心してください。書き方をちょっと工夫するだけで、この悲劇は簡単に防げます。
—
5. リフローを最小限に抑える!実務で使えるデザイン・コーディングパターン
ブラウザの負担を減らし、滑らかに動くWebサイトを作るための実践的なテクニックをいくつか伝授しましょう。
テクニック①:アニメーションは「レイアウトを伴わないプロパティ」を使う
要素を動かしたり、拡大・縮小したりするときに `width` や `top` を使っていませんか?
代わりに、`transform`(移動・拡大縮小) や `opacity`(透明度) を使ってみてください。
これらは、レイアウト(位置の再計算)の工程をスキップして、GPUという専用のハードウェアにお任せできる(これを合成=コンポジットと呼びます)ため、驚くほど滑らかに動きます。
/ ⭕ おすすめの書き方:transformならレイアウトが起きない! /
.card {
transition: transform 0.3s ease;
}
.card:hover {
/ 要素を少し大きくするだけなら、widthではなくtransformを使う /
transform: scale(1.05);
}
テクニック②:DOMの読み書きを分離する(バッチ処理の思想)
もしJavaScriptでどうしても要素の大きさを取得したり変更したりする場合は、「書き込む処理」と「読み込む処理」をバラバラに混ぜず、きれいに整頓(バッチ処理)しましょう。
// ⭕ 推奨される書き方:読み込みと書き込みをまとめる
// 1. まず現在の状態をまとめて「読む」
const currentWidth = box.offsetWidth;
// 2. その後で、まとめて「書き込む」
requestAnimationFrame(() => {
box.style.width = (currentWidth + 10) + ‘px’;
});
ブラウザに「ちょっと待ってね、計算はあとでまとめてやっていいからね」と伝えるイメージです。これだけでブラウザのストレスは激減します。
—
おわりに:ブラウザと仲良くなろう
いかがでしたでしょうか?
「レイアウト(リフロー)」という言葉を聞くと難しく感じるかもしれませんが、要するに「ブラウザが部屋の模様替えをする大工仕事」のことです。
私たちがCSSを書くとき、「あ、今このプロパティを書いたから、ブラウザは今からリビングの家具を動かそうと頑張ってるんだな」と、頭の片隅でブラウザの動きを想像してあげられるようになるだけで、書くコードの質は劇的に変わります。
最初は全部を意識できなくても全然大丈夫です。「あ、アニメーションさせるときは `transform` を使えばいいんだっけ」という引き出しを一つ持つだけでも、あなたの作るWebサイトはぐっと軽快で、ユーザーにとって心地よいものになりますよ。
それでは、快適なフロントエンドライフを!次の記事でお会いしましょう。

コメント