Professor Sloth

Free web performance master class

Learn about web performance and how to make your site faster, delivered straight to your inbox.

Measuring Largest Contentful Paint (LCP)

Measuring Largest Contentful Paint (LCP)

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:

Largest Contentful Paint Example
Largest Contentful Paint Example. The current LCP element is highlighted in blue.

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 threshold recommendations from Google.
Largest Contentful Paint threshold recommendations from Google.

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 });
Basic use of the Largest Contentful Paint API

Note that the buffered: true option returns all entries that occurred before the PerformanceObserver was configured. The sloth example page returns entries like this:

LargestContentfulPaint performance entries
LargestContentfulPaint performance entries

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 });
Don't measure Largest Contentful Paint in background tabs

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
}
Detect Largest Contentful Paint API with try/catch

3. LargestContentfulPaint Entries Can “Revert” To Previous Values

This Behavior Has Changed!

As of Chrome 88, previous LCP entries are not re-issued when the current largest element is deleted. Instead, the deleted element remains the last LCP entry until a larger paint occurs.

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:

Largest Contentful Paint reverts on element removal.
Largest Contentful Paint Reverts to former value after element removal.

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:

Largest Contentful Paint: Unexpected largest element
Largest Contentful Paint: Unexpected "largest" element

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:

User Interactions Stop LargestContentfulPaint measurements
User Interactions Stop LargestContentfulPaint measurements

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.

Looking for more? Check out the Definitive Guide to Measuring Web Performance.

Todd H. Gardner
CEO Request Metrics

Todd is a software engineer, business leader, and developer advocate with 20+ years of experience. He is a co-founder and CEO of TrackJS and Request Metrics, and previously a independent consultant who helped build products at Thomson Reuters, Reach Local, and LeadPages.