Largest Contentful Paint (LCP) is a measurement of how long the largest element on the page takes to render. It’s one of several Web Vital metrics that measure how real users perceive the performance of modern web applications. New measurements like Largest Contentful Paint are increasingly important as JavaScript and SPA’s render more content after page load is completed.
Largest Contentful Paint
The Largest Contentful Paint metric works under the assumption that the page is useful to the user once they can see the largest piece of content. It’s an important “core web vital” metric that Google will soon be considering when ranking search results.
LCP is not a single measurement, but a series of measurements. An additional LargestContentfulPaint
entry is created every time a new largest element is rendered. The LCP metric can be boiled down to a single value by using the last LargestContentfulPaint entry in a page load. Only image, video and text-containing block level elements can trigger LCP entries.
What constitutes “largest” varies by element type. Image element size is determined by the size of the image as shown on the page. Text-containing element size is the smallest box than encompasses the text itself.
In this contrived example, the largest rendered element is highlighted. Some elements are in the base HTML and rendered right away. Later, JavaScript inserts additional elements:
But what is a good value for Largest Contentful Paint? Helpfully, Google has determined some recommended times using data gathered from the Chrome browser:
Largest Contentful Paint API
The Largest Contentful Paint API is a proposed standard to expose largest paint measurements through JavaScript. It is currently supported in Blink-based browsers, such as Chrome, Edge, and Opera. NOTE: As a draft standard, there are occasionally changes to how LCP is determined.
We can test the API’s behavior with a little code:
new PerformanceObserver(entryList => {
console.log(entryList.getEntries());
}).observe({ type: "largest-contentful-paint", buffered: true });
Note that the buffered: true
option returns all entries that occurred before the PerformanceObserver was configured. The sloth example page returns entries like this:
LCP Production API Quirks and Gotchas
The API example above glossed over a few issues and surprising behavior that need to be considered before being used in a production setting.
1. Don’t Measure Pages Loaded In The Background!
Last Contentful Paint should not be measured when the page is loaded in a background tab. The measurement only indicates when the user first brought the tab to the foreground in that case. An additional check prevents measurement of background tabs:
var hiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity;
document.addEventListener('visibilitychange', (event) => {
hiddenTime = Math.min(hiddenTime, event.timeStamp);
}, { once: true });
new PerformanceObserver(entryList => {
entryList.getEntries().forEach((entry) => {
if (entry.startTime < hiddenTime) {
// This entry occurred before the page was hidden
console.log(entry);
}
};
}).observe({ type: "largest-contentful-paint", buffered: true });
2. Largest Contentful Paint API Feature Detection
Not all browsers support the Largest Contentful Paint API. Try/catch is the only reliable way to detect the feature because some browsers throw an exception when the API is used:
try {
new PerformanceObserver(entryList => {
console.log(entryList.getEntries());
})
// Some browsers throw when 'type' is passed:
.observe({ type: "largest-contentful-paint", buffered: true });
}
catch (e) {
// The Largest Contentful Paint API is not supported by this browser
}
3. LargestContentfulPaint Entries Can “Revert” To Previous Values
Previous LargestContentfulPaint
entries can be re-issued if the current “largest element” is removed from the DOM. The last entry returned from entryList.getEntries()
has a shorter startTime
than the previous entry when this happens:
4. A Block Element’s Border and Background Do Not Contribute To Its Size
The “largest” element in LargestContentfulPaint entries can be rather un-expected. Often, the visually largest element is not largest according to the LCP size rules. This happens because borders and colored backgrounds are not included in an element’s size calculation. Only the text’s bounding box is used:
5. User Interaction Stops Further LCP Entries
New LargestContentfulPaint
entries are created while content continues to render and the user has not interacted with the page. As soon as the page is clicked or scrolled, LCP measurements are halted. Ironically, users who interact with a slow page out of frustration can hide the actual largest paint:
Conclusion
As the above quirks show, Largest Contentful Paint doesn’t always tell the whole story. It is just another tool in the web performance toolbox. When paired with traditional performance measurements and other new ones like Cumulative Layout Shift, a better understanding of your users’ experience can be seen.
LCP Performance Monitoring
Let us handle the hard stuff. Monitor your real-user web vitals like Largest Contentful Paint with Request Metrics.
Top comments (0)