Using First Contentful Paint - FCP
Tags: webdev, webperf, devops, performance
Published: 2021-05-12 15:15:45

---
title: Using First Contentful Paint - FCP
published: true
date: 2021-05-12 00:00:00 UTC
tags: webdev, webperf, devops, performance
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/irh7lkb4svnw68e0j9wh.png
canonical_url: https://requestmetrics.com/web-performance/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](https://developers.google.com/search/blog/2020/05/evaluating-page-experience). Check out how FCP compares with other performance metrics in [The Definitive Guide to Measuring Web Performance](https://requestmetrics.com/web-performance/measure-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.

![FCP in the Loading Waterfall](https://requestmetrics.com/assets/images/webperf/fcp/fcp_loading_waterfall_740.png)<figcaption>FCP in the Loading Waterfall</figcaption>

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.

![FCP Metric Range](https://requestmetrics.com/assets/images/metrics/fcp_range_400.png)<figcaption>FCP Metric Range</figcaption>

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`](https://developer.mozilla.org/en-US/docs/Web/API/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:

```javascript
new PerformanceObserver((entryList) => {
    console.log(entryList.getEntriesByName("first-contentful-paint"));
}).observe({ type: "paint", buffered: true });
```
<figcaption><a href="#code-197">Example of First Contentful Paint API</a></figcaption>

Unlike the [Largest Contentful Paint](https://requestmetrics.com/web-performance/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:

![FCP Performance Entry](https://requestmetrics.com/assets/images/webperf/fcp/fcp_observer_api.png)<figcaption>FCP Performance Entry</figcaption>

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](https://github.com/GoogleChrome/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:

```javascript
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 });

```
<figcaption><a href="#code-550">Don't Background Pages</a></figcaption>

#### 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.

```javascript
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 */ }
```
<figcaption><a href="#code-317">Detect Largest Contentful Paint API with try/catch</a></figcaption>

#### 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](https://requestmetrics.com/web-performance/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](https://requestmetrics.com/web-performance/measure-web-performance).