レイアウト再計算(リフロー)と再描画(リペイント)

ウェブページのレンダリングにおいて、リフロー(レイアウト再計算)リペイント(再描画) はブラウザがコンテンツの更新を処理する際の2つの重要なプロセスです。以下に詳細なメカニズムと最適化方法を解説します。

1. 基本概念

  1. リペイント(再描画)
  • 色や背景色などの視覚的なスタイル変更が発生した場合、ブラウザは対象要素の描画のみを更新します。
  • レイアウト計算を伴わないため、処理コストが比較的軽いです。
  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. デバッグ方法

  1. Chrome DevTools Performanceパネル
  • レイアウト処理や描画の時間分布を可視化
  1. Renderingパネルの利用
  • レイアウト変化領域(青色ハイライト)
  • 再描画領域(緑色ハイライト)の表示

6. 比較表

特性 リフロー(Layout) リペイント(Repaint)
発生条件 寸法・位置の変化 色・透明度の変化
コスト 高い(全体再計算) 中程度(部分描画)
依存関係 リペイントを必ず引き起こす リフローを引き起こさない
最適化ポイント DOM操作のバッチ化 不要なスタイル変更の回避

基本原則

  • 強制リフローの回避:スタイル変更後に即座にレイアウトプロパティを読み取らない
  • CSSアニメーションの優先transformopacityプロパティを使用
  • オフラインDOM操作DocumentFragmentや非表示要素の活用

このメカニズムの理解は、特に複雑なインタラクションやアニメーション処理におけるパフォーマンス向上に大きく寄与します。

タグ: javascript CSS Web性能最適化 DOM操作 ブラウザレンダリング

5月21日 00:14 投稿