1. はじめに
このセクションは規定ではありません。
ウェブブラウザの主な目的は、HTML、CSS、画像リソースをユーザーのために画面上のピクセルへ変換することです。ウェブページのパフォーマンス測定は、多くの場合、これらの作業(テキストや画像などのコンテンツを画面に描画する)の所要時間を計測することに関係します。こうしたタイミングの使い方には、ページのパフォーマンスやロード時のユーザー体験を評価する様々な方法がありますが、根本的にはどれも時間を測定する共通の手段から始まります。
これはペイントタイミングを一般的な仕組みとして測定する方法を定める基礎的なドキュメントです。この基盤を用いて、First Paint(最初のペイント)およびFirst Contentful Paint(最初の内容ペイント)の指標を定義します。ペイント測定の他の具体的な事例については、他の文書で定められる場合があります。
具体的に、本仕様では以下を扱います:
-
画像がデコードされペイント準備が整う時刻の測定
-
要素が描画される時刻の測定
-
描画された要素のサイズの測定
-
描画された要素が目に見えるコンテンツを含むかどうかの判定
1.1. 最初のペイントおよび最初の内容ペイント
ロードは単一の瞬間ではなく、単一の指標で完全に捉えられるものではありません。ロード体験には、ユーザーが「速い」と感じるか「遅い」と感じるかに影響する複数の瞬間があります。
First Paint(FP)はその重要な瞬間の最初であり、続いてFirst Contentful Paint(FCP)が続きます。これらの指標は、ブラウザが指定されたドキュメントを描画するタイミングを示します。これはユーザーにとって「何かが起きているか?」という疑問に答える重要な瞬間です。
両指標の主な違いは、FPがブラウザがそのドキュメントで何かを初めて描画した時点を示すのに対し、FCPはDOMから最初の画像またはテキストコンテンツが描画された時点を示すことです。
1.2. 使用例
const observer= new PerformanceObserver( function ( list) { const perfEntries= list. getEntries(); for ( const perfEntryof perfEntries) { // エントリーの処理 // 分析や監視のための報告 // ... } }); // ペイントタイミング通知のためのオブザーバ登録 observer. observe({ entryTypes: [ "paint" ]});
2. 用語
ペイント:ユーザーエージェントが「ペイント」(または「レンダー」)を実行したとは、レンダーツリーを画面上のピクセルに変換したことを指します。正式には、ユーザーエージェントがイベントループのレンダリングの更新ステップを実行したときに「レンダー」されたとみなします。
注意: レンダリング処理は非常に複雑であり、タイムスタンプはユーザーエージェントがこのパイプラインで記録できる最新のタイムスタンプ(ベストエフォート)であるべきです。通常、このAPIではフレームがOSへ表示のため送信される時刻が推奨されます。
生成コンテンツ疑似要素は、以下すべてを満たす場合ペイント可能疑似要素です:
CSS画像 imgは、以下すべてを満たす場合内容画像です:
DOMString
は、非空であるとは、文書の空白文字以外の文字を1文字以上含む場合です。
要素 targetは、次のいずれかを満たす場合内容有りです:
-
targetがテキストノードを子に持ち、非空テキストを表し、そのノードのused opacityが0より大きい。
注意: これは組版疑似要素がテキストノードのopacityを上書きする場合をカバーします。
-
targetがbackground-imageとして内容画像を持ち、used background-sizeの幅と高さが0でない値である。
-
targetが
canvas
で、context modeがnone
以外に設定されている。 -
targetが描画された子孫を持つsvg要素である。
-
targetが起点要素で、ペイント可能疑似要素を表し、それが内容画像または非空テキストを表す。
要素は、以下のいずれかの場合タイミング対象です:
ペイント可能境界矩形を要素targetで計算するには、次の手順を実行します:
-
boundingRectを
getBoundingClientRect()
をtargetで実行した結果とする。 -
boundingRectを返す。
注意: overflow
やoverflow
なボックスに含まれる要素は、ペイント可能境界矩形がクリップされません。どちらの場合でも、要素はスクロール操作で可視化できるためです。
要素 elは、次の全てを満たす場合ペイント可能です:
-
elが描画されている。
-
elの使用済みのvisibility は
visible
です。 -
elおよび全ての祖先のused opacityが0より大きい。
注意:
ペイント可能
な要素でも、例えばテキストが背景色と同じ場合など、ユーザーに見えない場合があります。これらの要素も最初の内容ペイントの計算にはペイント可能と見なします。 -
elのペイント可能境界矩形が文書のスクロール領域と交差している。
注意: 要素がゼロサイズに拡大縮小されている場合、
display
や: nonedisplay
で空の矩形になる場合などをカバーします。: contents注意: 一般的に、要素はビュー ポート内か、スクロールやズームによってビュー ポート内になる可能性があるならペイント可能です。
最初のペイントエントリには、ユーザーエージェントがナビゲーション後に初めてレンダーした時刻を示すDOMHighResTimeStamp
が含まれます。これはデフォルトの背景ペイントを除外しますが、非デフォルトの背景ペイントやiframeの囲みボックスは含みます。これはページロードで開発者が関心を持つ最初の重要な瞬間、すなわちユーザーエージェントがページのレンダリングを開始した瞬間です。
ブラウジングコンテキスト ctxは、以下のいずれかを満たす場合ペイントタイミング対象です:
-
ctxが最上位ブラウジングコンテキストである。
-
ctxが入れ子ブラウジングコンテキストで、ユーザーエージェントがctxにペイントタイミング報告を設定している。
注意: これにより、ユーザーエージェントはメインフレーム以外の一部フレームに対してのみペイントタイミングを有効化できます。例えば、ユーザーエージェントがメインフレームの情報を漏らす可能性がある場合、クロスオリジンiframeに対してペイントタイミングを無効化することもできます。
3. ペイントタイミングミキシン
このセクションは規範的ではありません。
PaintTimingMixin
インターフェースは、レンダリングサイクルに関連するタイムスタンプを公開します。
これは、PerformanceEntry
を拡張したプラットフォームオブジェクトに含まれます。具体的には、PerformanceElementTiming
、
LargestContentfulPaint
、
PerformanceEventTiming
、
PerformancePaintTiming
、
およびPerformanceLongAnimationFrameTiming
によって拡張されます。
paintTime
属性は、レンダリングの更新ループの終了時点のタイムスタンプを表し、
presentationTime
は、フレームがユーザーに提示される際にマークされる実装固有のタイムスタンプを表します。
HTML標準でレンダリングの更新から呼び出されるペイントタイミングのマークアルゴリズムが両方の属性を設定します。
ペイントタイミングに依存するエントリーの属性、例えばLargestContentfulPaint
の
renderTime
(およびそのstartTime
)は、通常、デフォルトのペイントタイムスタンプを返します。これにより、presentationTime
の実装固有の性質に依存しません。
3.1. PaintTimingMixin
インターフェース
[Exposed =Window ]interface mixin {
PaintTimingMixin readonly attribute DOMHighResTimeStamp ;
paintTime readonly attribute DOMHighResTimeStamp ?; };
presentationTime
PaintTimingMixin
インターフェースミキシンを含むオブジェクトには、関連付けられたペイントタイミング情報(nullまたはペイントタイミング情報)があります。
ペイントタイミング情報は、 構造体です。以下の項目を持ちます:
- レンダリング更新終了時間
- 実装依存の提示時間
-
Null または
DOMHighResTimeStamp
paintTime
属性のゲッターステップは、this
の ペイントタイミング情報 の レンダリング更新終了時間 を返します。
presentationTime
属性のゲッターステップは、存在する場合、this の ペイントタイミング情報 の 実装依存の提示時間 を返します。
ペイントタイミング情報 paintTimingInfo のデフォルトペイントタイムスタンプを取得するには、 paintTimingInfo の 実装依存の提示時間 が null でない場合はそれを返し、それ以外の場合は paintTimingInfo の レンダリング更新終了時間 を返します。
4. PerformancePaintTiming
インターフェイス
[Exposed =Window ]interface :
PerformancePaintTiming PerformanceEntry { [Default ]object (); };
toJSON PerformancePaintTiming includes PaintTimingMixin ;
PerformancePaintTiming
は PerformanceEntry
インターフェイスの下記属性を拡張します:
-
name
属性のgetterは、最小限のフレーム属性付けのためにDOMString
を返す必要があります。nameの可能な値は以下の通りです:-
:first paint のため"first-paint" -
:first contentful paint のため"first-contentful-paint"
-
-
entryType
属性のgetterは
を返す必要があります。"paint" -
startTime
属性のgetterは、ペイントが発生した時刻のDOMHighResTimeStamp
を返す必要があります。 -
duration
属性のgetterは 0 を返す必要があります。 -
toJSON が呼び出されたとき、default toJSON steps を
PerformancePaintTiming
に対して実行してください。
NOTE: PerformancePaintTiming
を実装するユーザーエージェントは、
を supportedEntryTypes
に含める必要があります。
グローバルオブジェクト の ブラウジングコンテキスト が paint-timing eligible である場合です。
これにより、開発者は特定の ブラウジングコンテキスト に対してペイントタイミングのサポートを検出できます。
5. 処理モデル
5.1. 関連付けられた画像リクエスト
各 Element
には 関連付けられた画像リクエスト があり、これは 画像リクエスト または null で、初期値は null です。
Element
型の element の処理モデルが
HTMLImageElement
,
SVGImageElement
,
または HTMLVideoElement
が新しい画像リソース(例:画像やポスター画像として表示されるため)を作成するとき、
element の 関連付けられた画像リクエスト は作成された画像リソースの 画像リクエスト に設定されます。
Note: URLの
scheme が "data" である画像リソースは、取得されませんが依然として読み込む必要がある 画像リクエスト
を持ちます。このリクエストは Element
の 関連付けられた画像リクエスト となり得ます。
Note: 現在の記述は具体的な アルゴリズムには言及していないため曖昧です。該当する処理モデルがより統一された処理モデルを持つ場合、より厳密に記述できます。
全ての Element
は 関連付けられた背景画像リクエスト
のリストを持ち、初期値は空の配列です。Element
element のスタイルが新しい画像リソース(背景画像として表示されるため)を必要とする場合、新しいリソースによって作成された 画像リクエスト が element の 関連付けられた背景画像リクエスト に追加されます。
NOTE: Element
は複数の 画像リクエスト を持つことができます。例えば、
background-image プロパティが複数値を持つ場合です。下記例では、一つの background-image プロパティが4つの
画像リクエスト を生成し、それぞれが下記アルゴリズムで記録・報告されます。
<!DOCTYPE html> < style > div { background-image : url( https://images.example/background1.png ), url( https://images.example/background2.png ); } </ style > < div ></ div > < div ></ div >
5.2. ペイントタイミングの記録
pending image record は、以下の 構造体の 要素を持つものです。
-
element、
Element
-
request、画像リクエスト
-
loadTime、
DOMHighResTimeStamp
Element
は所有テキストノード集合(初期値は空の順序付き集合で、Text
ノードを含む)を持ちます。
Document
は過去に報告されたペイント集合(初期値は空の順序付き集合で、文字列を含む)を持ちます。
Document
はレンダリング待ち画像(初期値は空のリストで、保留画像レコードを含む)を持ちます。
Document
は描画済みテキストを持つ要素集合(初期値は空の順序付き集合で、Element
を含む)を持ちます。
5.2.1. CSS仕様への修正
画像リクエスト
がElement
elementの関連背景画像リクエスト内で完全に利用可能となった場合、elementおよび画像リクエストを入力として読み込み完了画像の処理アルゴリズムを実行します。
5.2.2. HTML仕様への修正
Element
elementの関連画像リクエストが完全に利用可能となった場合、elementとその関連画像リクエストを入力として読み込み完了画像の処理アルゴリズムを実行します。
Text
ノードtextを初めてペイントしたとき、次の手順を実行してください:
-
textがフォントフェイスのフォントブロック期間のためにペイントされない場合は、戻る。
-
追加としてtextをelementの所有テキストノード集合に加える。
5.2.3. 読み込み完了画像の処理
Element
elementと画像リクエスト imageRequestを入力として実行するには:
-
rootをelementのルートとする。
-
rootが
Document
でなければ、戻る。 -
nowをelementの現在の高精度時刻(elementの関連グローバルオブジェクトに基づく)とする。
-
recordを保留画像レコード(element element、request imageRequest、loadTime now)とする。
-
recordをrootのレンダリング待ち画像に追加する。
5.3. ペイントタイミングの報告
5.3.1. 最初の内容ペイント
-
documentの過去に報告されたペイント集合に
が含まれていれば、falseを返す。"first-contentful-paint" -
それ以外の場合はfalseを返す。
5.3.2. ペイントタイミングのマーク
-
documentのブラウジングコンテキストがペイントタイミング対象でない場合は戻る。
-
paintTimingInfoを新しいペイントタイミング情報(そのレンダリング更新終了時刻はdocumentの現在の高精度時刻)とする。(documentの関連グローバルオブジェクトに基づく)
-
paintedImagesを新しい順序付き集合とする。
-
paintedTextNodesを新しい順序付き集合とする。
-
docのレンダリング待ち画像リストの各recordについて:
-
recordのrequestが利用可能かつペイント準備ができていれば、次の手順を実行:
-
recordをpaintedImagesに追加。
-
recordをdocのレンダリング待ち画像リストから削除。
-
-
-
Element
elementをdocの子孫の各要素について:-
elementがdocの描画済みテキストを持つ要素集合に含まれていれば、続行。
-
elementの所有テキストノード集合が空なら、続行。
-
追加としてelementをdocの描画済みテキストを持つ要素集合に加える。
-
追加としてelementを paintedTextNodesに加える。
-
-
reportedPaintsをdocumentの過去に報告されたペイント集合とする。
-
frameTimingInfoをdocumentの現在のフレームタイミング情報とする。
-
documentの現在のフレームタイミング情報をnullに設定する。
-
flushPaintTimingsを以下の手順とする:
-
reportedPaintsが
を含まず、ユーザーエージェントが最初のペイントのマークを設定している場合、ペイントタイミングを報告をdocument、"first-paint"
、paintTimingInfoを指定して呼び出す。"first-paint" 注意: 最初のペイントはデフォルト背景ペイントを除外しますが、非デフォルト背景ペイントは含みます。
-
documentが最初の内容ペイントを報告すべきなら:
-
ペイントタイミングを報告をdocument、
、paintTimingInfoを指定して呼び出す。"first-contentful-paint"
注意: 親フレームは子iframeのペイントイベントを認識せず、逆も同様です。つまりiframeのみを含むフレームは最初のペイント(iframeの囲みボックスによる)を持ちますが、最初の内容ペイントは持ちません。
注意: documentは
や"first-paint"
を必ずしもマークするとは限りません。完全に空のdocumentは最初のペイントをマークしない場合があり、documentが内容有りでない要素のみを含む場合は最初の内容ペイントをマークしない場合があります。"first-contentful-paint" 注意: 最初のペイントのマークは任意です。ペイントタイミングを実装するユーザーエージェントは、少なくとも最初の内容ペイントはマークすべきです。
-
-
最大内容ペイントの報告をdocument、paintTimingInfo、paintedImages、paintedTextNodesで呼び出す。
-
要素タイミングの報告をdocument、paintTimingInfo、paintedImages、paintedTextNodesで呼び出す。
-
frameTimingInfoがnullでなければ、長いアニメーションフレームエントリをキューをdocument、frameTimingInfo、paintTimingInfoで呼び出す。
-
-
ユーザーエージェントが実装定義の表示時刻をサポートしない場合、flushPaintTimingsを呼び出して戻る。
-
以下の手順を並行して実行:
-
現在のフレームがユーザーに表示された実装定義タイミングまで待機。
-
documentのクロスオリジン分離能力がfalseなら:
-
グローバルタスクをキューをパフォーマンスタイムラインタスクソースにdocumentの関連グローバルオブジェクトを指定して、flushPaintTimingsを実行する。
-
5.3.3. ペイントタイミングの報告
-
新しい
PerformancePaintTiming
オブジェクトnewEntryをdocumentの関連レルムで作成し、以下の属性を設定する:-
newEntryの
name
属性にpaintTypeを設定。 -
newEntryの
entryType
属性に
を設定。"paint" -
newEntryの
startTime
属性にデフォルトペイントタイムスタンプ(paintTimingInfoで取得)を設定。 -
newEntryの
duration
属性に0を設定。
-
-
newEntryのペイントタイミング情報にpaintTimingInfoを設定。
-
追加としてpaintTypeをdocumentの過去に報告されたペイント集合に加える。
5.4. 共通アルゴリズム
5.4.1. ペイントタイミング向け公開
Element elementがペイントタイミング向け公開かどうかを、Documentまたはnull documentを入力として判定するには、以下の手順を行う:
-
elementが接続済みでなければ、falseを返す。
-
documentがnullの場合、documentをelementの関連設定オブジェクトの関連グローバルオブジェクトの関連付けられたdocumentとする。
-
documentが完全にアクティブでなければ、falseを返す。
-
elementのルートがdocumentと一致しなければ、falseを返す。
-
trueを返す。
6. 謝辞
この仕様の技術的な貢献・提案を通じて改善に導いてくださった全てのコントリビューターに特別な感謝を表します。