1. Introduction
Load is not a single moment in time — it’s an experience that no one metric can fully capture. There are multiple moments during the load experience that can affect whether a user perceives it as "fast" or "slow".First Paint (FP) is the first of these key moments, followed by First Contentful Paint (FCP). These metrics mark the points, immediately after navigation, when the browser renders pixels to the screen. This is important to the user because it answers the question: is it happening?
The primary difference between the two metrics is FP marks the point when the browser renders anything that is visually different from what was on the screen prior to navigation. By contrast, FCP is the point when the browser renders the first bit of content from the DOM, which may be text, an image, SVG, or even a canvas element.
1.1. Usage Example
var observer = new PerformanceObserver(function(list) { var perfEntries = list.getEntries(); for (var i = 0; i < perfEntries.length; i++) { // Process entries // report back for analytics and monitoring // ... } }); // register observer for long task notifications observer.observe({entryTypes: ["paint"]});
2. Terminology
Paint: the browser has performed a "paint" (or "render") when it has converted the render tree to pixels on the screen. This is formally defined as the when "update the rendering" happens in event loop processing.
NOTE: The rendering pipeline is very complex, and the timestamp should be the latest timestamp the browser is able to note in this pipeline (best effort). Typically the time at which the frame is submitted to the OS for display is recommended for this API.
First Paint entry contains a DOMHighResTimeStamp reporting the time when the browser first rendered after navigation. This excludes the default background paint, but includes non-default background paint. This is the first key moment developers care about in page load – when the browser has started to render the page.
First Contentful Paint entry contains a DOMHighResTimeStamp reporting the time when the browser first rendered any text, image (including background images), non-white canvas or SVG. This includes text with pending webfonts. This is the first time users could start consuming page content.
3. Paint Timing
Paint Timing involves the following new interface
3.1. PerformancePaintTiming
interface
interface PerformancePaintTiming
: PerformanceEntry {};
PerformancePaintTiming
extends the following attributes of PerformanceEntry
interface:
-
The
name
attribute must returnDOMString
for minimal frame attribution. Possible values of name are:-
first-paint
: for First Paint -
first-contentful-paint
: for First Contentful Paint
-
-
The
entryType
attribute must return"paint"
. -
The
startTime
attribute MUST return aDOMHighResTimeStamp
of when the paint occured. -
The
duration
attribute MUST return 0.
4. Processing Model
4.1. Modifications to other specifications
4.1.1. HTML: event loop processing model
During step 7.12 in "update the rendering":
-
For each fully active Document in docs, update the rendering or user interface of that Document and its browsing context to reflect the current state, and invoke §4.2.1 Mark Paint Timing while doing so.
4.2. Reporting Paint Timing
4.2.1. Mark Paint Timing
Perform the following steps:
-
If this instance of update the rendering is the first paint, then record the timestamp as paint-timestamp and invoke §4.2.2 Report Paint Timing algorithm with two arguments: string "first-paint" and paint-timestamp.
NOTE: First paint excludes the default background paint, but includes non-default background paint.
-
If this instance of update the rendering is the first contentful paint, then record the timestamp as paint-timestamp and invoke §4.2.2 Report Paint Timing algorithm with two arguments: string "first-contentful-paint" and paint-timestamp.
NOTE: This paint must include text, image (including background images), non-white canvas or SVG.
-
Otherwise, do nothing and return.
4.2.2. Report Paint Timing
Given two arguments paint-type and paint-timestamp, perform the following steps:
-
Create a new
PerformancePaintTiming
object newEntry and set its attributes as follows:-
Set newEntry’s name attribute to paint-type
-
Set newEntry’s entryType attribute to
paint
-
Set newEntry’s startTime attribute to paint-timestamp
-
Set newEntry’s duration attribute to 0.
-
-
Add the PerformanceEntry newEntry object.
5. Acknowledgements
Special thanks to all the contributors for their technical input and suggestions that led to improvements to this specification.