リフローとリペイント入門
ブラウザが画面を描き直すしくみを、図とデモで見てみよう。
1. ひとことで言うと?
リフロー(Reflow)
要素の位置や大きさを計算し直すこと。「レイアウト」とも呼ばれます。
🏠 家具の配置換え:ソファを大きくしたら、周りの家具も全部動かして測り直す。
リペイント(Repaint)
形や位置はそのままで見た目(色など)だけ塗り直すこと。
🎨 壁の塗り替え:家具は動かさず、ペンキを塗り直すだけ。
配置換え(リフロー)をすると、そのあと必ず塗り直し(リペイント)も発生します。だからリフローのほうが重い処理です。
2. ブラウザが画面を作る流れ
HTMLとCSSを受け取ったブラウザは、次の順番で画面を作ります。
ポイントは「上の段からやり直すほど重い」ということ。②からやり直すのがリフロー、③からやり直すのがリペイントです。④だけで済む変更(transform など)がいちばん軽量です。
3. 図で見るリフロー
1つの箱の幅を広げると、後ろにある箱まで押し出されて位置が変わります。ブラウザは全員の位置を計算し直す必要があります。
4. 図で見るリペイント
色を変えるだけなら、大きさも位置も変わりません。その箱を塗り直すだけで済みます。
5. 触ってみよう:どの段階が動く?
ボタンを押すと、太枠の箱(A)のスタイルが変わり、ブラウザがやり直す段階が光ります。
6. どのプロパティで何が起きる?
| 発生するもの | 代表的なプロパティ・操作 |
|---|---|
| リフロー | width height margin padding border-width top/left font-size display、要素の追加・削除、テキストの変更、ウィンドウのリサイズ |
| リペイント | color background-color background-image border-color box-shadow outline visibility |
| 合成のみ | transform opacity(多くのブラウザで、別レイヤーになっている場合) |
※ 実際の挙動はブラウザや状況によって少し違います。「大きさ・位置が変わる=リフロー」と覚えておけば大丈夫です。
7. 気をつけたい「強制リフロー」
ブラウザは本来、変更をまとめてから1回だけリフローします。ところが、スタイルを変えた直後に offsetHeight などのサイズを読み取ると、ブラウザは正しい値を返すためにその場でリフローせざるを得ません。これをループの中でやると、何度もリフローが起きてしまいます(レイアウト・スラッシング)。
✕ 遅い書き方
const boxes = document.querySelectorAll('.box');
for (const box of boxes) {
// 読む(強制リフロー)→ 書く を繰り返している
box.style.width = box.offsetWidth + 10 + 'px';
}
◯ 速い書き方
const boxes = document.querySelectorAll('.box');
// ① 先にまとめて読む
const widths = [...boxes].map(box => box.offsetWidth);
// ② あとでまとめて書く
boxes.forEach((box, i) => {
box.style.width = widths[i] + 10 + 'px';
});
サイズを読み取るとリフローを起こしうるもの:offsetWidth/Height clientWidth/Height scrollTop getBoundingClientRect() getComputedStyle() など。
8. 軽くするためのコツ
- アニメーションは
transformとopacityで:leftやwidthを動かすと毎フレームリフローが起きます。transform: translateX()なら合成だけで済みます。 - スタイルはクラスでまとめて変える:
style.xxxを1つずつ書き換えるより、classList.add('active')で一度に変えるほうがわかりやすく効率的です。 - 読み取りと書き込みを分ける:上の「強制リフロー」を避けましょう。
- たくさんの要素は一度に追加:
DocumentFragmentにまとめてから DOM に入れると、追加のたびにレイアウトが走るのを防げます。 - DevTools で確認する:Chrome の「Performance」タブで記録すると、紫の Layout(リフロー)や緑の Paint(リペイント)がどれだけ起きているか見られます。
まとめ
- リフロー=位置・大きさの再計算。周りにも影響して重い。
- リペイント=色などの塗り直し。リフローより軽い。
- リフローが起きると、必ずリペイントも起きる。
- transform / opacity は合成だけで済むことが多く、アニメーション向き。
- 「読む」と「書く」を交互にしないのが大事。