1. 導入
このセクションは規範的ではありません。 LargestContentfulPaint APIは、開発者がウェブページの読み込みおよび描画プロセスを可視化し、最適化できるようにします。
開発者は、ユーザーの視覚的レンダリング体験と相関する信頼性ある指標を必要としています。First PaintやFirst Contentful Paintのような描画指標は初期のレンダリングに焦点を当てていますが、描画されたコンテンツの重要性を考慮していないため、ユーザーがまだそのページを有用だと感じていない時点を示す場合もあります。
Largest Contentful Paint(LCP)は以下のようなページ読み込み指標を目指します:
-
First PaintやFirst Contentful Paintよりユーザー体験とより強く相関する
-
理解・説明しやすい
-
恣意的操作(ゲーム化)の余地を減らす
ページ読み込み中の最大のペイントは、ユーザー視点から意味のあるイベントを示す可能性が高いため、デフォルトで開発者に公開し、パフォーマンスチームや分析プロバイダ、ラボベースの計測ツールが、コンテンツ制作者自身による追加注釈なしで指標を取得できるようにします。
このAPIは[PAINT-TIMING]で定義された概念に大きく依存しており、これはこの高レベル機能が基盤としている低レベルのプリミティブと見なすことができます。もしコンテンツ制作者が重要な点を注釈付けしたい場合は、[ELEMENT-TIMING] APIを使うことで、報告対象の要素をより柔軟に制御できます。
注意: Largest Contentful Paint APIは、タイミング適格な要素だけを公開します。Element Timingと異なり、Largest Contentful Paintのために要素へ注釈を追加する必要はありません。
1.1. 最大コンテンツ
このAPIで用いられるアルゴリズムは、これまで見つかったコンテンツを追跡します。新しい最大のコンテンツが見つかるたびに新しいエントリーが作成されます。削除されたコンテンツもアルゴリズムで考慮されます。特に、削除されたコンテンツが最大だった場合は、より大きなコンテンツが追加されたときにのみ新たなエントリーが作成されます。スクロールやインプットイベントが発生すると、その後サイトに新たなコンテンツが導入される可能性が高いため、アルゴリズムは終了します。
1.2. 使用例
次の例は画像と大量のテキストを表示します。その後、開発者がページ読み込み中に最大ペイントの候補エントリーを受け取るオブザーバーを登録します。
< img src = "large_image.jpg" > < p id = 'large-paragraph' > This is large body of text.</ p > ...< script > const observer= new PerformanceObserver(( list) => { let perfEntries= list. getEntries(); let lastEntry= perfEntries[ perfEntries. length- 1 ]; // Process the latest candidate for largest contentful paint }); observer. observe({ entryTypes: [ 'largest-contentful-paint' ]}); </ script >
1.3. 制限事項
このセクションは規範的ではありません。
LargestContentfulPaint API はヒューリスティックに基づいています。そのため、エラーが発生しやすいです。以下の 問題があります:
-
アルゴリズムは特定タイプのユーザー入力を検出すると停止します。しかし、これはユーザー入力が メインコンテンツ表示前に発生した場合、アルゴリズムがメインコンテンツを 捕捉できません。実際、ごく早くユーザー入力があると、アルゴリズムは無意味な結果や全く結果を 生成しない可能性もあります。
-
画像カルーセルを考慮するため、コンテンツが削除されてもなお最大のものとして 扱われます。これは、大きなコンテンツをプレースホルダーに使う スプラッシュスクリーンがあるウェブサイトでは問題となります。
LargestContentfulPaint API はドキュメントのロードに基づいています。したがって、以下のケースではリセットされません:
-
Back-forward cache(bfcache)からの復元。
-
JavaScript やリッチなアプリケーション内で使われる 同一ドキュメント履歴ナビゲーション。
LargestContentfulPaint API を利用する際、これらを API の外でどのように 取り扱うか検討する必要があるかもしれません。なぜなら、ユーザーが それらをページロードとみなす場合があるためです。
さらに、最初にオフスクリーンで読み込まれるページ(バックグラウンドタブや プリレンダリング技術によるものなど)は、ロードから描画までの 時間を計測するため、予想より大きな値を報告します。これについても どう対処するかを考える必要があります。
2. 用語
最大 コンテンツ描画候補は、以下のメンバーを含む構造体です:
注記: 最大 コンテンツ描画候補の要素は、DOM から削除された要素の リークを防ぐために、弱く格納できます。
3. 最大コンテンツの表示
最大コンテンツの表示には以下の新しいインターフェイスが関わります:
3.1. LargestContentfulPaint
インターフェース
[Exposed =Window ]interface :LargestContentfulPaint PerformanceEntry {readonly attribute DOMHighResTimeStamp ;loadTime readonly attribute DOMHighResTimeStamp ;renderTime readonly attribute unsigned long ;size readonly attribute DOMString ;id readonly attribute DOMString ;url readonly attribute Element ?; [element Default ]object (); };toJSON LargestContentfulPaint includes PaintTimingMixin ;
各LargestContentfulPaint
オブジェクトには、以下の関連する概念があります:
-
size(サイズ)、初期値は0。
-
loadTime(ロード時刻)、初期値は0。
-
id(ID)、初期値は空文字列。
-
url(URL)、初期値は空文字列。
-
関連付けられた
Elementを含む element(要素)、初期値は。null
entryType
属性のgetterは、DOMString
の を返さなければならない。
name
属性のgetterは空文字列を返さなければならない。
startTime
属性のgetterは、this の
renderTime
の値を返さなければならない。
duration
属性のgetterは 0 を返さなければならない。
renderTime
属性は、デフォルトペイントタイムスタンプを、this の ペイントタイミング情報
で指定して返さなければならない。
loadTime
属性は、this の loadTime の値を返さなければならない。
size
属性は、this の size の値を返さなければならない。
id
属性は、this の id
の値を返さなければならない。
url
属性は、this の url
の値を返さなければならない。
element
属性のgetterは次の手順を実行しなければならない:
-
this の element が paint timing用に公開されていない(引数null)場合、null を返す。
注記: 上記のアルゴリズムは、Document
の子孫でなくなった要素は
element
属性getterによって返されなくなり、シャドウDOM内の要素も含まれることを意味します。
この仕様は Document
を拡張し、次のものを追加します:
-
現在の最大コンテンツ描画 候補。最大コンテンツ描画候補または null であり、 初期値は null です。
4. 処理モデル
各Window
はスクロールイベントがディスパッチされたかというブール値を持ち、初期値はfalseです。
4.1. DOM仕様への修正
このセクションは[DOM]仕様が修正され次第、削除予定です。
ステップ1の直後に次のステップを追加:
-
targetのrelevant global objectが
Windowオブジェクトであり、eventのtypeがscrollであり、かつそのisTrustedがtrueであれば、targetのrelevant global objectのスクロールイベントがディスパッチされたかをtrueにする。
4.2. 最大コンテンツの表示を報告する
Document
document、描画タイミング情報 paintTimingInfo、順序付き
集合である保留中の画像レコード paintedImages、および順序付き
集合である要素 paintedTextNodesを与えて、最大コンテンツ描画を報告するよう
求められた場合は、次の手順を実行します。
注記: paintedImages内の各保留中の画像レコードと、 paintedTextNodes内の各テキスト要素は、その要素が描画可能(すなわち、不透明度と可視性を持つ)かつ コンテンツを含む(すなわち、画像リソースまたはブロッキングフォントが十分に読み込まれている)とみなされる 最初の描画について、描画タイミングを記録する処理から正確に一度だけ報告されます。
-
windowを、documentの関連する大域オブジェクトとします。
-
windowのスクロールイベントを配送済みまたは入力イベントを配送済みのいずれかが true の場合は、返ります。
-
newCandidateを、document、paintedImages、 paintedTextNodes、およびdocumentの現在の最大コンテンツ描画 候補を与えて、新しい最大コンテンツ描画候補を 算出する結果とします。
-
newCandidateが null の場合は、返ります。
-
documentの現在の最大コンテンツ描画 候補をnewCandidateに設定します。
-
entryを、newCandidate、paintTimingInfo、および documentを使用してLargestContentfulPaint エントリーを作成する結果とします。
-
entryであるPerformanceEntryをキューに入れます。
Document
document、順序付き集合である保留中の画像レコード paintedImages、順序付き
集合である要素 paintedTextNodes、および最大
コンテンツ描画候補または null であるcurrentCandidateを与えて、新しい最大
コンテンツ描画候補を算出するには、次の手順を実行します。この手順は、最大コンテンツ描画候補または null を返します。
-
currentSizeを、currentCandidateが null でない場合は currentCandidateのサイズとし、それ以外の場合は 0 とします。
-
largestSizeをcurrentSizeとします。
-
newCandidateを null とします。
-
paintedImagesの各recordについて反復します。
-
imageElementを、recordの要素とします。
-
documentを与えたとき、imageElementが描画タイミングに公開されていない場合は、 続行します。
-
intersectionRectを、imageElementをターゲット、ビューポートをルートとして 交差矩形アルゴリズムを使用したときに返される値とします。
-
resultを、intersectionRectおよびrecordのリクエストを与えたときの imageElementの実効視覚サイズとします。
-
resultが null の場合は、続行します。
-
resultのサイズが largestSize以下の場合は、続行します。
-
largestSizeを、resultのサイズに設定します。
-
newCandidateを、次の値を持つ新しい最大コンテンツ描画 候補に設定します。
-
-
paintedTextNodesの各textNodeについて反復します。
-
documentを与えたとき、textNodeが描画タイミングに公開されていない場合は、 続行します。
-
textNodeのアルファチャンネル値が <=0 であるか、不透明度 値が <=0 の場合:
-
textNodeのtext-shadow値が none であり、 textNodeのstroke-color値がtransparentであり、かつtextNodeのstroke-image値が none の場合は、続行します。
-
-
intersectionRectを、textNodeの所有するテキストノードの集合内のすべての
Textノードの境界ボックスの和集合を、視覚ビューポートと交差させたものとします。 -
resultを、intersectionRectおよび null を与えたときの textNodeの実効視覚サイズとします。
-
resultが null の場合は、続行します。
-
resultのサイズが largestSize以下の場合は、続行します。
-
largestSizeを、resultのサイズに設定します。
-
newCandidateを、次の値を持つ新しい最大コンテンツ描画 候補に設定します。
-
-
newCandidateが null でなく、かつcurrentSizeが 0 より大きい場合:
-
newCandidateを返します。
4.3. 要素の実効視覚サイズの判定
要素の実効視覚サイズを決定するには、 次の手順を実行します。
- 入力
-
intersectionRect、
DOMRectReadOnlyimageRequest、
Requestまたは nullelement、要素
document、文書
- 出力
-
実効視覚サイズ結果。これは、項目としてサイズ(数値)、幅(数値)、および高さ(数値)を持つ構造体であり、最大コンテンツ描画について報告する実効視覚サイズ、幅、および高さを ピクセル単位で表します。または、要素を LCP 候補とすべきでない場合は null です。
-
widthを、intersectionRectの
widthを 最も近い整数に切り上げた値とします。 -
heightを、intersectionRectの
heightを 最も近い整数に切り上げた値とします。 -
sizeを
widthとします。* height -
rootを、documentの閲覧コンテキストのトップレベル閲覧コンテキストのアクティブな文書とします。
-
rootWidthを、スクロールバーを除いたrootの視覚ビューポートの幅とします。
-
rootHeightを、スクロールバーを除いたrootの視覚ビューポートの高さとします。
-
sizeがrootWidthとrootHeightの積に等しい場合は、 null を返します。
-
imageRequestが null でない場合は、画像の位置と拡大を調整するために 次の手順を実行します。
-
imageRequestの応答のバイト単位のコンテンツ長が size * 0.004 未満の場合は、null を返します。
注記: このヒューリスティックは、 画像リソースに、利用者がコンテンツを含むものとして認識できるだけの十分なデータが含まれているかどうかを 検査します。転送されたファイルサイズと、復号および画像の拡大縮小を適用した後に実際に生成される ピクセル数を比較します。非常に少ないバイト数で極めて多数のピクセルを符号化する画像は、一般に、 コンテンツの少ない背景やグラデーションなどであり、LCP 候補とはみなされません。
-
concreteDimensionsを、element内における imageRequestの具体的なオブジェクトサイズとします。
-
visibleDimensionsを、object-positionまたはbackground-positionと、 elementのコンテンツボックスによる位置指定を考慮して調整した concreteDimensionsとします。
注記: これらの アルゴリズムの一部は、CSS で厳密に定義されていません。期待される結果は、element内の 画像の実際の位置とサイズを
DOMRectReadOnlyとして取得することです。 -
clientContentRectを、elementの変換を適用した visibleDimensionsを包含する最小の
DOMRectReadOnlyとします。 -
intersectingClientContentRectを、 clientContentRectとintersectionRectの交差部分とします。
-
widthを、intersectingClientContentRectの
widthを 最も近い整数に切り上げた値に設定します。 -
heightを、intersectingClientContentRectの
heightを 最も近い整数に切り上げた値に設定します。 -
sizeを
widthに設定します。* height注記: これにより、 要素の装飾ではなく、画像自体とのみ交差することが保証されます。
-
naturalAreaが 0 の場合は、null を返します。
-
boundingClientAreaを
clientContentRectのとします。width* clientContentRectのheight -
scaleFactorを
boundingClientAreaとします。/ naturalArea -
scaleFactorが 1 より大きい場合は、sizeを scaleFactorで除算します。
-
-
4.4. LargestContentfulPaint エントリーを作成する
LargestContentfulPaint
エントリーを作成するために、ユーザーエージェントは次の手順を実行しなければなりません。
- 入力
-
candidate、最大コンテンツ描画候補
paintTimingInfo、描画タイミング情報
document、
Document - 出力
5. セキュリティとプライバシーに関する考慮事項
このAPIは低レベルのプリミティブとしてPaint Timingに依存しています。同様のElement Timing APIと異なり、LCPはたとえ小さい要素であっても、ページ読み込み時点までで最大であればタイミング詳細を開示する可能性があります。しかし、これはElement Timingが既に可能にしている範囲を超えた機微な情報は公開しないと思われます。