ウェブページのレンダリングにおいて、リフロー(レイアウト再計算) と リペイント(再描画) はブラウザがコンテンツの更新を処理する際の2つの重要なプロセスです。以下に詳細なメカニズムと最適化方法を解説します。
1. 基本概念
- リペイント(再描画)
- 色や背景色などの視覚的なスタイル変更が発生した場合、ブラウザは対象要素の描画のみを更新します。
- レイアウト計算を伴わないため、処理コストが比較的軽いです。
- リフロー(レイアウト再計算)
- 幅や高さ、マージンなどの寸法や位置情報の変更が発生すると、ブラウザは要素の幾何学的属性を再計算し、レンダリングツリーを更新します。
- リペイントを必ず引き起こすため、処理コストが非常に高いです。
2. トリガー要因
リフローを引き起こす操作
// サイズ変更
element.style.width = "200px";
element.style.height = "150px";
// マージン/パディング変更
element.style.marginLeft = "20px";
element.style.paddingRight = "10px";
// DOM構造変更
const newItem = document.createElement("div");
document.getElementById("container").appendChild(newItem);
// 画像サイズ変更
const image = document.getElementById("logo");
image.style.height = "100px";
リペイントを引き起こす操作
// 色・背景変更
element.style.color = "blue";
element.style.backgroundColor = "#f0f0f0";
// 表示状態変更
element.style.visibility = "hidden";
element.style.border = "2px dashed red";
3. 性能への影響
- リフローはリペイントよりコストが高い レイアウト再計算は全体のレンダリングツリーの再評価が必要で、複数の要素が影響を受ける可能性があります。
- ブラウザの最適化
複数の変更を一度にまとめたバッチ処理が行われますが、
getBoundingClientRect()などレイアウトプロパティの読み取りは即時リフローを強制します。
4. 最適化手法
1. 変更操作のバッチ化
// 非効率的な実装
element.style.top = "50px";
element.style.left = "100px";
// 最適化例(CSSクラス変更)
element.classList.add("new-position");
2. DocumentFragmentによるDOM操作
const fragment = document.createDocumentFragment();
for (let i = 0; i < 50; i++) {
const item = document.createElement("li");
fragment.appendChild(item);
}
document.getElementById("menu").appendChild(fragment);
3. レイアウトプロパティのキャッシュ
// 非効率的な実装
const width = element.offsetWidth;
element.style.width = (width + 20) + "px";
// 最適化例
const cachedWidth = element.offsetWidth;
requestAnimationFrame(() => {
element.style.width = (cachedWidth + 20) + "px";
});
4. 合成層の利用
/* GPUアクセラレーションを活用 */
.animation {
transform: translate3d(50px, 0, 0);
opacity: 0.7;
will-change: transform;
}
5. ドキュメント外での変更処理
// 要素を非表示に
element.style.display = "none";
// 複数のスタイル変更
element.style.fontSize = "16px";
element.style.lineHeight = "1.5";
// 再表示
element.style.display = "block";
5. デバッグ方法
- Chrome DevTools Performanceパネル
- レイアウト処理や描画の時間分布を可視化
- Renderingパネルの利用
- レイアウト変化領域(青色ハイライト)
- 再描画領域(緑色ハイライト)の表示
6. 比較表
| 特性 | リフロー(Layout) | リペイント(Repaint) |
|---|---|---|
| 発生条件 | 寸法・位置の変化 | 色・透明度の変化 |
| コスト | 高い(全体再計算) | 中程度(部分描画) |
| 依存関係 | リペイントを必ず引き起こす | リフローを引き起こさない |
| 最適化ポイント | DOM操作のバッチ化 | 不要なスタイル変更の回避 |
基本原則:
- 強制リフローの回避:スタイル変更後に即座にレイアウトプロパティを読み取らない
- CSSアニメーションの優先:
transformやopacityプロパティを使用 - オフラインDOM操作:
DocumentFragmentや非表示要素の活用
このメカニズムの理解は、特に複雑なインタラクションやアニメーション処理におけるパフォーマンス向上に大きく寄与します。