How to Improve First Contentful Paint
Chances are, you've run a PageSpeed Insights test and noticed "First Contentful Paint" as one of the first numbers in the report.
I've covered most of the metrics before in my article on Understanding the Page Speed Metrics in Google Lighthouse, but in this article I wanted to dive deeply into First Contentful Paint - particularly what it is, what a good score is, and how to improve.
Table of Contents
- What is First Contentful Paint (FCP)
- What's a good First Contentful Paint (FCP) score?
- Ways to reduce First Contentful Paint (FCP)
What is First Contentful Paint (FCP)
First Contentful Paint is a performance metric measured by Google Lighthouse and PageSpeed Insights. It measures the amount of time it takes the browser to show the first visible (as in, above the fold - the portion of the webpage visible without scrolling) block of text, or image (including SVGs) on your page. Iframes aren't counted when measuring FCP.
What's a good First Contentful Paint (FCP) score?
Google considers FCP values of:
- less than 2 seconds as fast
- greater than 2 seconds, but less than 4 seconds as moderate
- greater than 4 seconds as slow
Ways to reduce First Contentful Paint (FCP)
Reduce Time To First Byte (TTFB)
In case you're not familiar, TTFB measures the amount of time your server takes to respond to the browser's request. Since First Contentful Paint includes the amount of time it takes the server to send us our data, improving TTFB will also improve our First Contentful Paint.
There are two ways to improve your TTFB:
Reduce the amount of time spent on the server processing the request (this includes the time your server spends on database queries, API calls, and load balancing).
- The simplest way to reduce this is to upgrade your server's RAM and CPU specs, or pick a better hosting provider.
- Alternatively, look at optimising your backend code, though this is significantly easier said than done, particularly if using a CMS like WordPress or Drupal.
Reduce the amount of time spent sending the request from the server to the browser
- The simplest way to reduce this is to use a CDN, and enable GZIP or Brotli compression.
Resize your images
This an extremely simple, yet often overlooked step. Some frameworks like WordPress have plugins that do this automatically, but some plugins fail to do this well.
There are two steps:
- Open your image in macOS Preview or Microsoft Paint, resize the image, making it smaller. For example, if you have a photo that's 4000x3000, I'd make it 1000x750.
- Now that the image is physically smaller, run it through an image optimiser. I use TinyJPG for this, but there are hundreds of options.
These two steps alone will save you 67% or more.
Lazy load your images below the fold
In other words - ensure your above the fold images aren't being lazy loaded. All other content should be lazy loaded.
In WordPress, lazy loading was typically enabled via plugin - as of WordPress 5.4, all images are lazy loaded by default.
If you're using a React framework like Next.js, and using the
next/image package to load your hero/above the fold images, ensure you pass the
priority prop. Next/image uses lazy loading by default, so you could be taking a hit on your First Contentful Paint without realising it.