CSSOM ツリーと DOM ツリーを組み合わせてレンダリング ツリーを作成し、表示可能な各要素のレイアウトを計算し、画面にピクセルをレンダリングするペイント プロセスへの入力として使用します。これらの各ステップを最適化することは、最適なレンダリング パフォーマンスを実現するうえで重要です。
オブジェクト モデルの構築に関する前のセクションでは、HTML と CSS の入力に基づいて DOM ツリーと CSSOM ツリーを構築しました。ただし、どちらもドキュメントのさまざまな側面をキャプチャする独立したオブジェクトです。1 つはコンテンツを記述し、もう 1 つはドキュメントに適用する必要があるスタイルルールを記述します。この 2 つを統合して、ブラウザが画面上のピクセルをレンダリングできるようにするには、どうすればよいでしょうか。
まとめ
- DOM ツリーと CSSOM ツリーを組み合わせてレンダリング ツリーを形成します。
- レンダリング ツリーには、ページのレンダリングに必要なノードのみが含まれます。
- Layout は、各オブジェクトの正確な位置とサイズを計算します。
- 最後のステップはペイントです。最終的なレンダリング ツリーを取り込んで、ピクセルを画面にレンダリングします。
まず、ブラウザは DOM と CSSOM を組み合わせて「レンダリング ツリー」を作成します。このツリーでは、ページ上のすべての表示可能な DOM コンテンツと、各ノードのすべての CSSOM スタイル情報をキャプチャします。
レンダリング ツリーを構築するために、ブラウザはおおまかに次の処理を行います。
DOM ツリーのルートから、表示されている各ノードを走査します。
- 一部のノード(script タグ、メタタグなど)は表示されず、レンダリングされる出力に反映されないため省略されます。
- 一部のノードは CSS で非表示になり、レンダリング ツリーからも省略されています。たとえば、上記の例の span ノードは、「display: none」プロパティを設定する明示的なルールがあるためにレンダリング ツリーに含まれていません。
表示されているノードごとに、一致する適切な CSSOM ルールを見つけて適用します。
コンテンツとコンピューティング スタイル付きの可視ノードを出力します。
最終出力は、画面上のすべての表示コンテンツのコンテンツとスタイル情報の両方を含むレンダリング ツリーです。レンダリング ツリーを配置したら、「レイアウト」ステージに進むことができます。
ここまでで、表示するノードとその計算されたスタイルを計算しましたが、デバイスのビューポート内の正確な位置とサイズについては計算していません。これが「レイアウト」ステージであり、「リフロー」とも呼ばれます。
ページ上の各オブジェクトの正確なサイズと位置を把握するため、ブラウザはレンダリング ツリーのルートから順に走査します。では、次の簡単な実践例を見てみましょう。
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Critial Path: Hello world!</title>
</head>
<body>
<div style="width: 50%">
<div style="width: 50%">Hello world!</div>
</div>
</body>
</html>
上記のページの本文には、ネストされた 2 つの div が含まれています。1 つ目の親(親)の div でノードの表示サイズをビューポート幅の 50% に設定し、2 つ目の div(親)で幅を親の 50%(ビューポートの幅の 25%)に設定します。
レイアウト プロセスの出力は「ボックスモデル」であり、ビューポート内の各要素の正確な位置とサイズを正確にキャプチャします。すべての相対測定値は、画面上の絶対ピクセルに変換されます。
表示されているノードと、そのノードで計算されたスタイルとジオメトリがわかったので、この情報を最終ステージに渡すことができます。最終ステージでは、レンダリング ツリー内の各ノードが画面上の実際のピクセルに変換されます。このステップは多くの場合、「ペインティング」または「ラスタライズ」と呼ばれます。
ブラウザは多くの処理を行う必要があるため、この処理には時間がかかることがあります。しかし、Chrome DevTools を使うと、前述の 3 つの段階すべてに関するインサイトを得ることができます。元の「Hello World」の例のレイアウト ステージを確認してみましょう。
- 「Layout」イベントは、タイムラインでのレンダリング ツリーの構築、位置、サイズの計算をキャプチャします。
- レイアウトが完了すると、ブラウザは「Paint Setup」イベントと「Paint」イベントを発行し、レンダリング ツリーを画面上のピクセルに変換します。
レンダリング ツリーの構築、レイアウト、ペイントの実行に必要な時間は、ドキュメントのサイズ、適用されたスタイル、動作しているデバイスによって異なります。ドキュメントが大きいほど、ブラウザの作業量が多くなり、スタイルが複雑になるほど、ペイントにかかる時間も長くなります(たとえば、ソリッドカラーはペイントが「安価」、ドロップ シャドウは計算とレンダリングに「コストがかかります」など)。
ページがようやくビューポートに表示されます。
以下に、ブラウザの手順をまとめます。
- HTML マークアップを処理し、DOM ツリーを構築します。
- CSS マークアップを処理し、CSSOM ツリーを作成します。
- DOM と CSSOM を組み合わせてレンダリング ツリーを作成します。
- レンダー ツリーでレイアウトを実行して、各ノードのジオメトリを計算します。
- 個々のノードを画面に描画します。
デモページはシンプルに見えますが、かなりの作業が必要です。DOM または CSSOM のいずれかが変更された場合、画面上で再レンダリングする必要があるピクセルを把握するために、このプロセスを繰り返す必要があります。
クリティカル レンダリング パスの最適化とは、上記のシーケンスのステップ 1 ~ 5 の実行に要する合計時間を最小限に抑えるプロセスです。これにより、コンテンツが可能な限り早く画面にレンダリングされ、最初のレンダリング後の画面更新の間隔も短縮されます。つまり、インタラクティブ コンテンツのリフレッシュ レートが高くなります。