LCPのElement Render Delayを最適化する
ダウンロードから表示まで:Largest Contentful PaintのElement Render Delay部分を改善する方法を学びましょう。

このガイドは、当社のCore Web VitalsリソースセンターのLargest Contentful Paint (LCP)セクションの一部です。Element Render Delayは、LCPタイムラインにおける最終フェーズであり、LCPリソースのダウンロードが完了してから、画面上に視覚的に描画されるまでのギャップを表します。
LCPのElement Render Delayを最適化する
4つのLCPフェーズのうち、Element Render Delayは最も誤解されています。各チームはTTFBを最適化し、Resource Load Delayを排除し、アセットを圧縮してResource Load Durationを短縮します。そして、ネットワークのウォーターフォールが完了したのを見て、作業が終わったと勘違いします。それは間違いです。
Element Render Delayとは、LCPリソースのダウンロードが完了してから、ユーザーの画面上に要素が完全に描画されるまでの時間です。これはネットワークの問題ではなく、メインスレッドの問題です。レンダリングの遅延が大きいということは、ブラウザが画像やフォントを保持していても、他のタスクで忙しすぎて実際に描画できないことを意味します。この遅延はLCPスコアに直接的に重くのしかかり、すべてのネットワークリクエストが完了した後に200ミリ秒以上追加されることもあります。
正確な定義:ラストマイル問題
Element Render Delayは、LCPリソース(画像ファイルやWebフォントなど)の最後のバイトがブラウザに到達した瞬間に始まります。そして、LCP要素が画面上に視覚的に描画されたときに終わります。これは、文字通り最後のステップです。
システムフォントを使用するテキストベースのLCP要素の場合、外部リソースを必要としないため、この遅延は多くの場合ゼロになります。しかし、LCP要素が画像であったり、カスタムWebフォントを使用している大多数のサイトでは、このフェーズが最大のボトルネックになることがよくあります。ブラウザは、ダウンロードしたビットを可視ピクセルに変換するという、CPUバウンドなタスクにこの時間を費やします。
「なぜ」起こるのか:渋滞した組み立てライン
レンダリングの遅延を修正するには、ブラウザがページを描画する仕組みを理解する必要があります。これは多くの場合、クリティカルレンダリングパスと呼ばれる複数段階のプロセスです。工場の組み立てラインと考えてください。
- 設計図の構築 (DOMとCSSOM): ブラウザはHTMLを解析してDocument Object Model (DOM) を構築し、CSSを解析してCSS Object Model (CSSOM) を構築します。これらは、ページコンテンツとそのスタイリングの設計図です。
- 設計図の結合 (レンダーツリー): DOMとCSSOMは結合され、ページのレンダリングに必要なノードのみを含むレンダーツリーになります。
<head>のような要素や、display: none;が指定された要素は除外されます。 - ジオメトリの計算 (Layout): ブラウザは、レンダーツリー内のすべての要素の正確なサイズと位置を計算します。このステージは「リフロー」とも呼ばれます。
- ピクセルへの色付け (Paint): ブラウザは、テキスト、色、画像、境界線、影を考慮して、各要素のピクセルを塗りつぶします。
- レイヤーの組み立て (Composite): ページは異なるレイヤーに描画され、正しい順序で組み立てられて最終的な画面画像が作成されます。
Element Render Delayは、これら最後のステージであるLayout、Paint、Compositeで消費される時間です。この組み立てライン全体は、メインスレッドという単一の作業員によって実行されます。その作業員が時間のかかるJavaScriptタスクの実行や、巨大なCSSファイルの解析で忙しい場合、組み立てラインは停止してしまいます。LCP画像はすでに到着しているかもしれませんが、メインスレッドが空いて処理と描画が行われるのを荷積み場で待っている状態なのです。
Element Render Delayを特定する方法
この問題の診断は、厳密な2段階のプロセスに従います。最初のステップを飛ばさないでください。
ステップ 1: フィールドデータ (RUM) で検証する
DevToolsを開く前に、Element Render Delayが実際のユーザーにとって現実的な問題であることを確認する必要があります。私自身のツールであるCoreDashのような、プロフェッショナルグレードのReal User Monitoring (RUM) ツールが不可欠です。これにより、サイトのLCPが4つのサブパートに分解されます。RUMデータで75パーセンタイルにおいて有意なElement Render Delayが示されている場合、解決すべき影響の大きい問題があることが検証されたことになります。
ステップ 2: DevToolsで診断する
RUMで問題のあるページを特定したら、Chrome DevToolsのPerformanceパネルを使用して原因を分析します。
- Performanceタブに移動し、「Web Vitals」チェックボックスを有効にします。
- 「Record and reload page」ボタンをクリックします。
- 「Timings」トラックで、LCPマーカーをクリックします。下部の「Summary」タブに、4つのLCPフェーズそれぞれの正確な所要時間が表示されます。Element render delayの値を書き留めます。
- 次に、タイムラインのMainトラックを調べます。LCPリソースのネットワークリクエストの終了とLCPタイミングマーカーの間に発生しているロングタスク(赤い角を持つ黄色のブロック)を探します。これらのタスクが遅延の直接的な原因です。それらの上にカーソルを合わせて、原因となっているスクリプトを特定します。
一般的な原因と効果的な解決策
Element Render Delayが大きい場合、ほぼ常にメインスレッドのブロックが原因です。
原因:レンダリングをブロックするCSS
問題: デフォルトでは、CSSはレンダリングをブロックします。ブラウザは、<head>にリンクされているすべてのCSSファイルをダウンロードして解析するまで、ピクセルを描画しません。大きく複雑なスタイルシートはメインスレッドを数百ミリ秒にわたって占有し、LayoutやPaintステージの開始を遅らせる可能性があります。サイトが複数のスタイルシートを読み込み、それぞれに個別のネットワークリクエストと解析サイクルが必要になると、この問題はさらに悪化します。CSSのpayloadを削減するための詳細な戦略については、未使用のCSSを削除するに関するガイドをご覧ください。
解決策: CSSを小さく、クリーンで、キャッシュ可能なものにします。
- 未使用のCSSを削除する: これは最も影響の大きい最適化です。大規模なサイトでは、未使用のCSSがスタイルシート全体のサイズの70%以上を占めることがあります。PurgeCSSのようなツールを使用すると、HTMLとJavaScriptをスキャンして未使用のセレクタを特定できます。不要なルールを削除することで、ダウンロード時間とメインスレッドでの解析時間の両方が短縮されます。
- 小さくキャッシュ可能なスタイルシートを目指す: CSSファイルの最適なサイズは、およそ10〜15kB(圧縮時)です。それより小さいと並行リクエストが多すぎになり、それぞれに接続のオーバーヘッドが発生するリスクがあります。それより大きいと、特に低速なモバイルネットワークにおいてブロック時間が増加します。その範囲の適切に構造化された単一のスタイルシートであれば、ダウンロードと解析が迅速に行われ、再訪問時のためにブラウザにキャッシュされます。
- CSSのインライン化は最後の手段にする: クリティカルCSSを
<style>ブロックにインライン化すると、最初のページ読み込み時のネットワークリクエストは排除されますが、代償が伴います。インライン化されたCSSはブラウザでキャッシュできません。再訪問するユーザーは、ページごとにそれを再ダウンロードすることになります。再訪問ユーザーがいるほとんどのサイトでは、ブラウザがキャッシュする小さな外部スタイルシートを使用する方が良い選択です。インライン化が意味を持つのは、再訪問ユーザーが非常に少ないランディングページのみです。
CSSの影響の定量化: CSSがレンダリングの遅延にどの程度寄与しているかを測定するには、Chrome DevToolsのCoverageタブを開きます(Ctrl+Shift+Pを押して「Coverage」と入力)。ページを読み込み、CSSファイルの未使用バイトの割合を確認します。未使用のCSSの割合が高い場合は、クリーンアップによってElement Render Delayが減少するという明確なシグナルです。
原因:長いJavaScriptタスク
問題: これが最も一般的な原因です。フレームワーク、分析スクリプト、A/Bテストツール、または十分に最適化されていないコードなど、重いJavaScriptの実行はメインスレッドを独占する可能性があります。単一の長時間実行されるタスクはレンダリングを数百ミリ秒ブロックし、Element Render Delayを直接増加させます。Googleは、ロングタスクを50ミリ秒以上かかるタスクと定義しており、200ミリ秒を超えるタスクは致命的に長いと見なされます。JavaScriptの遅延戦略の完全なコレクションについては、JavaScriptを遅延させる14の方法に関する記事をご覧ください。
解決策: 作業を分割します。
- メインスレッドへのyield: ロングタスクは小さなチャンクに分割する必要があります。これは、
setTimeout(..., 0)や新しいscheduler.yield()APIを使用して、定期的にブラウザに制御をyieldすることで実現できます。これにより、ブラウザはタスク間でレンダリングの更新を実行できるようになります。 - サードパーティの最適化と遅延: すべてのサードパーティスクリプトを監査します。初期レンダリングに不可欠でない場合は、
defer属性を使用して読み込むか、ページの読み込み後に挿入します。A/Bテスト用のスクリプトは、設計上レンダリングをブロックすることが多いため、特に問題になります。 - 視覚的な更新に
requestAnimationFrameを使用する: ページ読み込み中にJavaScriptでDOM操作を実行する必要がある場合は、その作業をrequestAnimationFrameでラップします。これにより、作業が次のペイントの直前に実行されるようにスケジュールされ、ブラウザがJavaScriptの操作間にフレームをレンダリングする機会を確実に得られます。
DevToolsでロングタスクを特定する
Chrome DevToolsのPerformanceパネルでは、ロングタスクは「Main」トラックの右上隅に赤い三角形がある黄色のブロックとして表示されます。どのスクリプトが原因かを特定するには:
- Performanceパネルでページの読み込みを記録します。
- TimingsトラックでLCPマーカーを見つけます。
- Mainトラックで、LCPリソースのネットワークリクエスト完了とLCPマーカーの間に発生しているロングタスクを調べます。
- これらのタスクをクリックすると、Summaryパネルにコールスタックが表示されます。コールスタックから、ロングタスクの原因となっているソースファイルと関数が明らかになります。
よくあるサードパーティの原因
実際のコンサルティング経験に基づくと、Element Render Delayを引き起こす最も一般的なサードパーティスクリプトには以下のものがあります:
- A/Bテストツール(Optimizely、VWO、AB Tasty):バリアント間のコンテンツのちらつきを防ぐために、意図的にレンダリングをブロックすることがよくあります。実験の決定をサーバー側(サーバーサイドテスト)に移すことで、この問題は完全に解消されます。
- 同期タグを使用するタグマネージャー: 同期(非非同期)タグで設定されたタグマネージャーは、レンダリングをブロックするスクリプトを挿入する可能性があります。コンテナを監査して、すべてのタグがDOMの準備完了後またはウィンドウの読み込み後に発火するように設定されていることを確認してください。
- 同意管理プラットフォーム: 決定が下されるまでレンダリングをブロックするCookie同意バナーは、LCPを遅延させる可能性があります。クリティカルレンダリングパスをブロックしない非同期実装を使用してください。
- チャットウィジェット: ライブチャットのスクリプトは、ページの読み込み時に重い初期化コードを実行することがよくあります。ページがインタラクティブになるまで読み込みを遅延させるか、ユーザーの操作(クリックなど)に応じて読み込むようにしてください。
原因:クライアントサイドレンダリング (CSR)
問題: 純粋なクライアントサイドレンダリングでは、初期のHTMLにLCP要素が存在しないことがよくあります。最初にJavaScriptを実行してDOMを構築し、LCP要素を挿入して、ようやくブラウザがそれをレンダリングできるようになります。このプロセス全体が、ひとつの巨大なレンダリング遅延となります。
解決策: サーバーでレンダリングします。他に方法はありません。Server-Side Rendering (SSR) または Static Site Generation (SSG) を使用して、サーバーから送信される初期のHTMLドキュメントにLCP要素が確実に存在するようにします。これにより、遅延の原因としてのJavaScript駆動のレンダリングフェーズ全体が排除されます。
原因:他のコードによって隠されたコンテンツ
問題: LCP要素がDOM内にあっても、CSS(例:opacity: 0)や、「スクロールで表示」するアニメーション、あるいはどのバリアントを表示するかまだ決定していないA/Bテストツールなどのスクリプトによって隠されている場合があります。要素はダウンロードされて準備ができていますが、まだ可視状態ではないため描画できません。
解決策: 即座に表示されるようにします。LCP要素については、初期読み込み時に要素を隠すようなエントリアニメーションやロジックを使用しないでください。要素はDOM内で表示可能であり、最初のペイントの時点から表示されるようにスタイル設定されている必要があります。A/Bテストツールを非同期で実行するように設定するか、LCP要素の可視性への影響を最小限に抑えるようにします。
原因:過大なDOMサイズ
問題: DOMサイズが大きい(1,500ノード以上)と、すべてのレンダリング操作のコストが増加します。各レイアウト計算、スタイルの再計算、およびペイント操作でより多くのノードを処理する必要があり、メインスレッドでより多くの時間がかかります。CSSとJavaScriptが適切に最適化されていても、肥大化したDOMはその膨大な量だけでレンダリング遅延を追加します。DOMサイズを削減するための詳細な戦略については、過大なDOMサイズを避けるに関するガイドをご覧ください。
解決策: 初期レンダリングに関与するDOMノードの数を減らします。
- HTML構造を簡素化する: 不要なラッパー要素を削除します。深くネストされた構造を平坦化します。レイアウトのために余分な
<div>要素を使用する代わりに、CSS GridまたはFlexboxを使用します。 - 長いリストを仮想化する: 何百ものリスト項目(製品グリッド、データテーブル)があるページでは、現在ビューポートに表示されている項目のみをレンダリングする仮想化ライブラリを使用します。
- ファーストビュー以下のコンテンツを遅延レンダリングする:
content-visibility: auto(後述)を使用して、画面外のセクションのレンダリングを完全にスキップします。
高度な戦術:レンダリングを完全に制御する
複雑なアプリケーションでは、メインスレッドをさらに制御する必要があります。
content-visibilityでパフォーマンスを解放する
CSSのcontent-visibilityプロパティは、大規模なページ向けに構築されています。ファーストビュー以下にあるページのセクションにcontent-visibility: auto;を設定することで、そのコンテンツがビューポートに入ろうとするまで、ブラウザにLayout、Paint、Compositeの作業をスキップできることを伝えます。これにより初期レンダリングのワークロードが削減され、メインスレッドが解放されてLCP要素をより早く描画できるようになります。
重要なのは、content-visibility: autoをcontain-intrinsic-sizeと組み合わせることです。これにより、隠されたコンテンツのプレースホルダーサイズが提供されます。これがないと、ブラウザは隠されたセクションの高さが分からないため、スクロールバーの動作が不安定になります。
/* Apply to below-the-fold sections */
.below-fold-section {
content-visibility: auto;
contain-intrinsic-size: auto 500px; /* Estimated height of the section */
}
/* Example: A long article page */
.article-comments {
content-visibility: auto;
contain-intrinsic-size: auto 800px;
}
.related-products {
content-visibility: auto;
contain-intrinsic-size: auto 600px;
}
.site-footer {
content-visibility: auto;
contain-intrinsic-size: auto 300px;
}
パフォーマンスへの影響: Chrome Developersのブログ記事によると、ブログページのファーストビュー以下のセクションにcontent-visibility: autoを適用すると、レンダリング時間が最大で7分の1に短縮されました。ブラウザはこれらのセクションのLayout、Paint、Compositeの作業を完全にスキップするため、メインスレッドはLCP要素を含むファーストビューのコンテンツに集中できるようになります。ブラウザのサポートは、Chromium、Firefox、Safari 18+など、すべてのモダンブラウザをカバーしています。
Web Workersによる作業のオフロード
Web Workersを使用すると、メインスレッドから完全に離れたバックグラウンドスレッドでJavaScriptを実行できます。Workerで実行される重い計算は、レンダリングをブロックしません。このサイト(corewebvitals.io)は分析処理にWeb Workerを使用しており、パフォーマンス上のメリットは確実なものです。メインスレッドは中断されることなく、描画のための空き状態を保つことができます。
とはいえ、Web WorkersはほとんどのWebサイトにおいて一般的なパターンではありません。個別のJavaScriptファイル、postMessageを介した通信が必要であり、DOMへのアクセス権はありません。ほとんどのCMSプラットフォームやサイトビルダーはこれを組み込みでサポートしていないため、カスタム開発なしでは実装が困難です。使用できる技術力がある場合、メインスレッドをクリアに保つための最も効果的な方法の1つです。しかし、ほとんどのチームにとっては、このページの他の最適化の方が実際の影響は大きくなるでしょう。
// main.js: Create a worker and send data for processing
const worker = new Worker('/js/analytics-worker.js');
// Offload heavy analytics processing to the worker thread
worker.postMessage({
type: 'process-events',
events: collectedEvents
});
// Receive results without blocking the main thread
worker.onmessage = (event) => {
console.log('Analytics processed:', event.data.summary);
};
// analytics-worker.js: Runs in a background thread
self.onmessage = (event) => {
if (event.data.type === 'process-events') {
// Heavy computation happens here, off the main thread
const summary = processEvents(event.data.events);
self.postMessage({ summary });
}
};
実際の世界への影響
- ケース 1:レンダリングをブロックするCSSのボトルネック: 大きなCSSファイルが顕著なレンダリング遅延を引き起こしていたサイトをDebugBearが分析しました。LCP画像はダウンロードされていましたが、ブラウザはCSSの解析に行き詰まっていました。単にクリティカルCSSをインライン化することで、ブラウザはHTMLが解析された直後にLCP要素を含むページコンテンツを描画できるようになり、スタイルシートによるレンダリング遅延が効果的に解消されました。
- ケース 2:A/Bテストのペナルティ: 大手Eコマースサイトでは、同期A/BテストスクリプトによってLCPが阻害されていることが判明しました。LCP画像は迅速にダウンロードされたにもかかわらず、どの製品画像を表示するかを決定する間、スクリプトがメインスレッドをブロックしていました。A/Bテストを、クリティカルでない要素については初期ページ読み込み後に実行するように移行したところ、LCPが即座に400ミリ秒以上改善され、そのすべてがElement Render Delayから回復したものでした。
チェックリスト:Element Render Delayを排除する方法
Element Render Delayが大きいことは、メインスレッドが混雑していることを示しています。解決策には、ブラウザが描画できるようにその混雑を解消することが含まれます。
- RUMで検証する: 最適化を始める前に、実際のユーザーデータを使用して、Element Render Delayが主要なLCPのボトルネックであることを確認します。
- 未使用のCSSを削除する: 決して適用されないCSSルールを監査して取り除きます。これは最も影響の大きい単一のCSS最適化です。PurgeCSSのようなツールや、DevToolsのCoverageタブを使用します。
- スタイルシートを小さく、キャッシュ可能に保つ: CSSファイルあたり約10〜15kB(圧縮時)を目指します。高速にダウンロードできるほど小さく、過剰な並行リクエストを避けられるほど大きいサイズです。再訪問者のためにブラウザにキャッシュさせます。
- 長いJavaScriptタスクを分割する: どの単一のスクリプトも50ミリ秒を超えて実行されるべきではありません。メインスレッドにyieldして、レンダリングの更新を許可します。
- サードパーティスクリプトを監査して遅延させる: 自問自答してください。各サードパーティスクリプトはページに配置する価値がありますか?初期ペイントに不可欠でないものはすべて遅延させます。
- SSRまたはSSGを使用する: LCP要素のレンダリングをクライアントサイドのJavaScriptに依存しないでください。完全に形成されたHTMLをサーバーから送信します。
- LCPが即座に表示されるようにする: ページの読み込み時にLCP要素を隠すアニメーション、スクリプト、スタイルをすべて削除します。
content-visibility: autoを使用する: 長いページの場合、画面外のコンテンツのレンダリングをスキップして、メインスレッドをファーストビューの描画のために解放するようにブラウザに指示します。- DOMサイズを削減する: 深くネストされたHTMLを平坦化し、不要なラッパーを削除し、長いリストを仮想化して、LayoutやPaint操作のコストを削減します。
次のステップ:LCPの最適化を続ける
Element Render Delayは最終フェーズです。4つすべてを網羅するには、以下を続けます:
- LCPの問題の修正と特定:フィールドデータとラボツールを使用して、すべてのLCP問題を見つけて修正するための完全な診断手法。
- LCP画像を最適化する:画像フォーマットの選択、レスポンシブ画像、プリロード、および一般的な画像最適化のミスについて。
- Resource Load Delay:ブラウザが可能な限り早くLCPリソースを発見できるようにします。これは多くの場合、LCPの最大の単一のボトルネックです。
- Resource Load Duration:圧縮、最新フォーマット、CDN設定、ネットワーク最適化を通じてダウンロード時間を短縮します。

