ようこそ、フロントエンドの奥深い世界へ。
私はこれまで、数えきれないほどのWebサイトが「なぜか重い」「カクつく」という現場に立ち会い、ブラウザの内部で悲鳴を上げているコードたちを救い出してきました。
今日は、初心者の方が必ずと言っていいほどぶつかる、そしてベテランでも油断すると足元をすくわれる「強制同期レイアウト(Forced Synchronous Layout, 通称FSL)」についてお話ししましょう。
「難しそうだな」と思わなくて大丈夫。ブラウザを「一生懸命に家を建てる大工さん」だと思って、リラックスして聞いてくださいね。
—
1. ブラウザは「一気にまとめてやりたい」派
まず、ブラウザが画面を描き出すまでの流れを、「設計図から家を建てる工程」に例えてみましょう。
1. スタイル計算: 「どの壁を青にするか?」を決める。
2. レイアウト(リフロー): 「壁の長さは何メートルか? どこに配置するか?」を計算する。
3. ペイント(リペイント): 「実際にペンキを塗る」。
4. コンポジット(合成): 「塗り終わったパーツを組み合わせて完成させる」。
ブラウザはとても効率を重視する性格なので、「100個のボタンの大きさを変えて」と言われたら、100回計算するのではなく、最後にまとめて一回だけ計算しようとします。その方が圧倒的に速いからです。
しかし、JavaScriptの書き方ひとつで、この「まとめてやりたいブラウザくん」の計画を台無しにしてしまうことがあります。それが強制同期レイアウトです。
—
2. 「強制同期レイアウト」って結局なに?
想像してみてください。大工さんが「よーし、これから100枚の壁を全部作り直すぞ!」と意気込んでいるときに、あなたが横からこう言ったとします。
「ねえ大工さん、今作業中の、その1枚目の壁の高さって今何センチ?」
大工さんは困ります。「いや、今から全部まとめて計算して作るところなんだよ。正確な数字が知りたければ、今すぐ作業を中断して、その1枚だけ先に計算して作らなきゃいけないじゃないか!」
これが強制同期レイアウトの正体です。
JavaScriptで「今の幅(offsetWidth)」や「今の高さ」を読み取ろうとすると、ブラウザは最新の値を答えるために、本来後でまとめてやりたかった「レイアウト計算」を、その瞬間に強制的に実行させられるのです。
—
3. なぜこれが「パフォーマンスの敵」なのか
一度だけならまだしも、これが「繰り返し(ループ)」の中で起きると大惨事です。
1. JavaScriptで1個目の要素のサイズを変える(「あとでやるリスト」に入る)
2. でも、直後にサイズを読み取るコードがある!
3. ブラウザ「仕方ない、今すぐ計算するよ…(計算実行)」
4. JavaScriptで2個目の要素のサイズを変える
5. またサイズを読み取るコードがある!
6. ブラウザ「えっ、また!? また今すぐ計算し直し…(計算実行)」
これを100回繰り返すと、ブラウザは100回も重たい計算を繰り返すことになります。画面がカクカクし、スマホの電池は熱くなり、ユーザーはストレスを感じてサイトを去ってしまいます。
—
4. ダメな例と、プロの解決策
では、実際のコードを見てみましょう。
「たくさんの箱の幅を、1つ前の箱と同じにする」という処理を例にします。
❌ ブラウザを疲れさせる書き方(NG例)
// 全てのボックスを取得
const boxes = document.querySelectorAll(‘.box’);
// ループの中で「書く(変更)」と「読む(取得)」を混ぜてしまう
for (let i = 1; i < boxes.length; i++) {
// 【読む】前の要素の幅を知りたい!(ここでブラウザに計算を強いる)
const lastBoxWidth = boxes[i - 1].offsetWidth;
// 【書く】今の要素の幅を変える
boxes[i].style.width = lastBoxWidth + 'px';
// 次のループの「offsetWidth」で、また再計算が発生する(地獄のループ)
}
✅ ブラウザに喜ばれる書き方(改善例)
プロは「まず全部読んでから、あとで一気に書く」という戦略をとります。
const boxes = document.querySelectorAll(‘.box’);
// 1. 【読む】必要な情報は、最初にまとめて変数に入れておく
// ※この例では単純化していますが、一括読み取りが基本です。
const firstBoxWidth = boxes[0].offsetWidth;
// 2. 【書く】変更作業だけをまとめて行う
for (let i = 1; i < boxes.length; i++) {
// ブラウザは「あとでまとめて計算すればいいや」とリラックスして作業できます
boxes[i].style.width = firstBoxWidth + 'px';
}
// ループが終わったあと、ブラウザはたった1回の計算で画面を更新します。
---
5. どうやって見つける?(検知のコツ)
「自分のコードが強制同期レイアウトを起こしているか不安…」という方も大丈夫。Google Chromeの「デベロッパーツール」が教えてくれます。
1. F12キーでデベロッパーツールを開き、「Performance」タブを選択します。
2. 録画ボタン(●)を押して、画面を操作し、停止します。
3. 記録されたグラフの中に、「Layout」という紫色のバーがあり、その右上に「小さな赤い三角のマーク」がついていたら要注意。
4. そこをクリックすると、「Forced Reflow(強制リフロー)」という警告とともに、原因となったコードの行数を教えてくれます。
この「赤い三角」を見つけたら、「おっと、大工さんを困らせていたな」と優しく修正してあげてください。
—
最後に:小さな気遣いが、最高のユーザー体験を作る
Web制作の学習を始めたばかりだと、どうしても「動くこと」を優先してしまいがちです。それは決して悪いことではありません。
でも、今回学んだ「ブラウザの気持ち(レンダリングの仕組み)」を少しだけ意識するだけで、あなたの作るサイトは劇的に滑らかになります。
- 「読み取り(Read)」は先に!
- 「書き込み(Write)」は後に!
このリズムを指先に覚え込ませてください。現場で活躍するエンジニアは、みんなこのリズムを大切にしています。
もし途中で分からなくなっても、いつでもこの場所に戻ってきてくださいね。ブラウザの仕組みは奥が深いですが、一歩ずつ進めば必ずあなたの強力な武器になります。応援していますよ!

コメント