Using First Contentful Paint - FCP
First Contentful Paint, or FCP, measures the time take to render the first element of a webpage. It’s a modern, user-centric measurement of how fast users see a response from your website. Here’s everything you need to know about the metric and how to use it.
FCP is one of the Core Web Vital performance metrics that measure user’s perceived performance of websites. These metrics are incredibly important to delivering fast user experiences, and avoiding SEO performance penalties. Check out how FCP compares with other performance metrics in The Definitive Guide to Measuring Web Performance.
First Contentful Paint Metric
The First Contentful Paint metric considers all the steps required to show the user the first bit of requested content. This includes the time for your servers to respond, network transfer time, HTML size and complexity, and required CSS assets.
In this case, Contentful refers to any text or image elements, but not the background color of the document.
Check out this example waterfall chart , and where FCP is marked.
Loading webpage images is not needed for FCP, but the browser does need to download all the CSS styles, including styles chained with @import
statements. Nesting multiple levels of styles can dramatically slow down your FCP performance.
Google defines the acceptable ranges for FCP to be less than 1.0 seconds. Anything over that risks a negative user experience and a possible ranking penalty. FCP scores larger than 3.0 seconds indicate a serious performance problem for your website.
Measuring FCP with PerformanceObserver
First Contentful Paint is measured using the PerformanceObserver
API and is supported in Blink-based browsers, such as Chrome, Edge, Android, and Opera. Other browsers, including Chrome on iOS, Safari, and Firefox, cannot report FCP metrics.
Here’s a little code to illustrate the API:
new PerformanceObserver((entryList) => {
console.log(entryList.getEntriesByName("first-contentful-paint"));
}).observe({ type: "paint", buffered: true });
Unlike the Largest Contentful Paint metric, there is not a dedicated type for FCP. You must listen to all paint events and filter them by name. The buffered
option allows you to gather data after it has happened. Paste in that code into DevTools on any page and you’ll see something like this:
Note that the measurement value is startTime
, not duration
. startTime
is when the FCP event started, while duration is how long the event lasted, which is usually 0.
Quirks, Gotchas, and Unexpected Behavior
Likely, you won’t be measuring FCP yourself. You’ll rely on a library like web-vitals or a service like Request Metrics to gather the data for you. But if you do want to measure FCP yourself, there are a few unexpected things you should look out for.
1. Don’t Measure Background Pages
Pages that are loaded in the background, such as opened in another tab or while minimized, will not have accurate FCP measurements. The first-contentful-paint
performance entry is fired once the page is viewed, which will be significantly slower than the actual loading time of the page.
You can detect whether a page is in the background and filter out metrics:
var hiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity;
document.addEventListener('visibilitychange', (event) => {
hiddenTime = Math.min(hiddenTime, event.timeStamp);
}, { once: true });
new PerformanceObserver(entryList => {
entryList.getEntriesByName("first-contentful-paint").forEach((entry) => {
if (entry.startTime < hiddenTime) {
// This entry occurred before the page was hidden
console.log(entry);
}
};
}).observe({ type: "paint", buffered: true });
2. Always Use Feature Detection
Many (most) browser do not support PerformanceObserver
or the paint
type. Some browsers, the object is not defined, while others will throw an error if you attempt to use it. Try/catch is the most reliable way to detect browser compatibility.
try {
new PerformanceObserver(entryList => {
console.log(entryList.getEntriesByName("first-contentful-paint"));
})
// Some browsers throw when 'type' is passed:
.observe({ type: "paint", buffered: true });
}
catch (e) { /* Not Supported */ }
3. Styles to the Document Don’t Count
Some pages will apply inline styles to their html
or body
elements, such as background-color, borders, or outlines. While these styles do paint to the screen, they are not considered for the first-contentful-paint metric.
Improving Your FCP Scores
FCP includes all the time waiting and fetching the document, CSS files, and synchronous scripts. You can improve your FCP scores by making your servers quick, your resources small and few, and the network hops short. Here are some common tactics that can help:
- Reduce server work and cache expensive actions
- Use compression on your HTML, CSS, and other resources
- Reduce the critical CSS required to render the page
- Use fewer and more efficient fonts
- Serve content through a CDN
- Use efficient http caching settings
All the improvements that you make to FCP will also help your Largest Contentful Paint scores.
Conclusion
The First Contentful Paint metric is an important part of the web performance story, but it’s not the only one! Learn more about the other web performance metrics and how to measure them in the Definitive Guide to Measuring Web Performance.