Fix & Identify Largest Contentful Paint (LCP) issues

Learn how to debug and fix all Largest Contentful Paint related issues on your page

Arjen Karel Core Web Vitals Consultant
Arjen Karel

Find and Fix Largest Contentful Paint (LCP) issues

In our previous article we talked about the Largest Contentful Paint. If you would like to read up on the basics this is a great place to start!

In this article I will focus on identifying the different Largest Contentful Paint issues and then explain how to fix them!

LCP TIP: most of the time the LCP will be much worse when the LCP is not a text element. That is why, when debugging the LCP it makes sense to log all LCP elements and their type!

Step 1: Check the LCP in search console

"The first step to recovery is admitting that you have a problem". So before we do anything to fix the Largest Contentful Paint let's make sure that we really have a problem with the interaction to next paint.

Log in to you Google Search Console. In the left menu click Core Web Vitals and select either Mobile or Desktop (tip: most of the times LCP issues are on mobile, so start with mobile)

Here you will see an overview of all Core Web Vitals related issues that are currently on your site. If one of these issues in LCP related we have confirmed there is a problem!

inp search console early warning

Step 2: Identify Largest Contentful Paint issues

Google Search console does not give you any information apart from URL groups to figure out what is causing the problems with the Largest Contentful Paint. So most of the times I see developers just blindly going in. They start deferring JavaScript (always, a great idea) and converting images to WebP (also a great idea) but that hardly ever fixes the LCP completely.

That is why, when improving the LCP, we will need to know exactly what is going in. We need to know:

  • Which elements will cause a bad LCP Score. First thing we need when debugging the LCP is to find the element that is most likely to become the LCP element. 
  • Is the Time to First Byte affecting the LCP? The TTFB is the first part of the LCP stage. When the TTFB is high it is impossible to pass the LCP. So fix this first!
  • Is the LCP element enqueued as early as possible? Once we ensured that the TTFB is not the problem we need to LCP element to start loading immediately when the page loads. If the element does not start loading immediately this is called a 'load delay'
  • Is the LCP element load time causing issues?When the TTFB and load delay have been eliminated the next step is to ensure the LCP elements have a relatively small filesize that wil allow them to be downloaded quickly over the network. We can use respionsive images or modern image formats like WebP oir AVIF to accomplish this. If the image does not download quickly this is called a 'load delay' 
  • Is the browser ready to paint once the LCP element is available? DFinally when the all other possible issues have been resolved the browser might not be able to start painting because it has scheduled other work. This is called a 'render delay'.
Now that we have a bit of background let's start fixing the LCP issues!

Set up RUM tracking

To get answers to all 6 questions above we need to measure the data is real life and log any of the problems that might happen with the Largest Contentful Paint. This is called Real User Monitoring and there are several ways to enable RUM tracking. The first is by leveraging the Web Vitals library and sending the results to your own analytics backend. The upside to this method is that it is cheap and flexible. The downside is that is might be a lot of extra work.

A good alternative to sending your Core Web Vitals data to your own backend is by using one of the many RUM tools our there. We have developed Core/Dash just for these use cases. Core/Dash is a low cost, fast and effective RUM tool that just get's the job done! Of course there are many RUM solutions out there and they will also do the job (at a higher price though)

coredash lcp by element type metric summary

Step 3: Find elements that cause a high LCP

The first thing that needs to be done is find the 'slowest' elements that cause the worst largest contentful paint scores. In CoreDash navigate to the LCP page and on the data table select elements to see the slowest elements. Click on the first element to filter your metrics by these types of elements.

coredash lcp by attribution element

Step 4: Zoom in to problems and fix!

Once you have selected the LCP element that you would like to fix, the LCP breakdown will give you all the hints that you need to fix your slow performing LCP elements. The breakdown shows the 75th percentile values of the 4 different loading stages of and LCP image element.

coredash lcp breakdown

When a page renders a lot might happen. Styles, scripts, fonts and images usually compete for network and CPU resources. Everything that happens, either network or CPU wise, before the LCP element has been painted will affect the Largest Contentful Paint.

It makes a lot of sense to break down 'everything that can happen ' before the Largest Contentful Paint into 4 categories:

  1. Time to first byte
  2. Resource load delay
  3. Resource load time
  4. Element render delay

Each of those categories can be optimized to improve the Largest Contentful Paint. Let's take a deeper look into those 4 categories that make up the LCP!

1. Improve the Time to first byte

The time to first byte is the time between the start of the page request and the first byte that has been received. Time to First Byte (TTFB) is a foundational metric. This means that any improvement on this metric will immediately reflect in a better LCP! Improving the time to first byte is a great idea regardless of the Largest Contentful Paint benefits.

resource ttfb lcp

Keep in mind: every resource has its own Time To First Byte. We are talking about the TTFB of the original HTML request

  1. Server side caching. Server side caching is one of the most effective ways to improve the TTFB. You can cache full pages, parts of the page, objects in memory or common database queries.
  2. Set up client side caching. Client side caching will improve (or rather eliminate) the TTFB for repeat visitors. Be careful though because with client side caching enabled visitors might see an older, cached version of a webpage that might even be be outdated.
  3. Consider using a CDN. A CDN stands between a visitor and the webserver . A CDN typically does not improve TTFB directly but since a CDN network is typically configured much much better then your average hosting server it might even give a small advantage in TTFB.
  4. Consider setting up static page caching. If you do use a CDN try to unlock the power of pull page edge caching. This means that you entire page is cached on CDN edge servers all over the world and can be served much faster then through your own origin server.
  5. Minimize your html. Every byte that you leave out will improve the TTFB. So enable gzip compression for your HTML, minify your HTML and be careful with inline resources like SVG's or too much structured data like JDON-ld.
  6. Set up your server correctly. This might be a bit technical but it setting up your web server for speed (HTTP/3, connection resumption, fast SSL ciphers etc). For example, according to CloudFlare HTTP/3 will give you a 12.5% better TTFB.

2. Improve resource load delay

The resource load delay is the time between the Time to First Byte and when the browser starts loading the LCP resource. This only applies when an Largest Contentful Paint element does not rely on a network resources. When the LCP element is a text element and font-display is set to swap or the font is a browser default font the LCP element does not have a resource load delay.

resource load delay lcp

The resource load delay is one of the most common issues that I have to fix. Consider this scenario: A slow wordpress website was 'fixed' with WP Rocket. The LCP image is now automatically lazy loaded. This means that the image will only be queued after all the stylesheets and scripts have loaded. On a slow mobile device this can easily take 7 or 8 seconds.

  1. Prioritize your LCP element with resource hints. The most effective way to eliminate resource load delay is to prioritize it with resource hints. There are 3 ways of doing this.
    1. The fastest way is to use 103-early-resource hints.
    2. A good alternative is preloading the LCP images
    3. The easiest but slightly slower way is to set fetchpriority="high" on the LCP element
  2. Avoid unnecessary resource hints. Resource hints are great ut when you prioritize the 'wrong' resources they will compete with the more important resources and slow down the Largest Contentful Paint
  3. Avoid background images. Background images, that are linked in a stylesheet, will only be enqueued after the stylesheet has been downloaded and rendered.
  4. Make sure your LCP element can be discovered by the preload scanner. The preload scanner is a small scanner that quickly scans your page for easy-to-discover, important elements. Lazy loaded images with the data-src attribute are not recognized by the preload scanner and will only be queued by the DOM Scanner. The DOM scanner will be blocked by StyleSheets and JavaScripts while the preload scanner is never blocked.
  5. Use font-display:swap or preload your webfonts. If you use webfonts the text elements might render only after the web-font has been downloaded. Web-fonts are only downloaded after they are found in the render tree (after the DOM has been generated and the CSS has been downloaded and parsed). That is why you should always preload important web-fonts and if possible use font-display="swap". The CSS property font-display:swap tells the browser that it is ok to render the text with a fallback font while the real web-font is being downloaded.

3. Improve resource load time

The resource load time is the time that it takes the resource to load. If you want to your Largest Contentful Paint to be fast it makes sense to minimize the network time it needs.

resource load time lcp
  1. Load LCP element from your main domain. A common mistake is to load the LCP element from another domain. This will require a whole new connection. It takes a relative long time to set up these new connections.
  2. Consider a CDN. A CDN can cache your static resources like images and serve them from edge servers all over the world that are much closer to the clients location.
  3. Set up client side caching. Client side caching will completely eliminate the resource load time for repeat visitors. Add an expires header to static resources to make sure they are client cacheable.
  4. Use newer, next-gen image formats. If you are still using jpg or png images consider converting these images to the newer WebP of Avif formats. These formats use a much better compression algorithm that will decrease the size of these images considerably. Smaller images mean faster downloading!
  5. Use responsive images. If your images are not responsive your mobile visitors will need to download desktop-sized images. Server smaller images to mobile visitors that will fit in the mobile viewport.
  6. Use HTTP/3. When you use the newest HTTP/2 or HTTP/3 protocol you can benefit from a lot of technical advantages like multiple parallel requests and better error handling. In short: newer HTTP protocols are much faster then the old ones.

4. Improve element render delay.

The element render delay is the time between when the browser has finished downloading the resource and the time it starts rendering the element. If the element cannot render immediately this is because the browser is busy. Usually this is because it is still downloading or parsing styles or the main thread is blocked by JavaScript.

resource render delay lcp

Improve render delay caused by StyleSheets.

When your LCP element is a text element (uncached) external stylesheet will always cause a render delay. When your LCP element is an image it will only cause a render delay if the Style-sheet downloading and parsing takes longer then the image to load.

  1. Use critical CSS. Critical CSS is a collection of the styles that is needed to render the visible viewport. These styles are placed inline, i the head of the page. The original styles are downloaded in parallel but are not render blocking. When done correctly Critical CSS will eliminate most of the render delay caused by CSS.
  2. Split up large CSS files. In some cases, it can be faster to split up large stylesheets into 2 or 3 separate stylesheets that are downloaded in parallel.
  3. Defer non-critical CSS. If styles are never in the visible viewport it makes sense to defer these stylesheets and load them in parallel.
  4. Minimize StyleSheets. Minimize your stylesheets by removing unused references and unneeded characters like spaces, tabs and newlines.
  5. Make stylesheets Cacheable. For repeat visitors, eliminate the LArgest Contentful Paint render delay completely by serving the CSS files directly from the browsers cache.
  6. Consider using a CDN. I have said it a few times. A well configured CDN will improve resource timing!

Improve render delay caused by JavaScript

JavaScript van delay the largest contentful paint in 2 ways. When a script is not deferred the browser will download and execute the script before it will start painting. When a script is deferred it might still block the main thread and delay the largest contentful paint.
  1. Remove unused JavaScript. Most pages have a lot of unused code. You can improve the Core Web Vitals (and not just the Largest Contentful Paint) by removing code that is not needed on the page.
  2. Defer or schedule JavaScript. Deferred JavaScript will download in parallel with the rest of the resources and will be executed at DOMContentReady.
  3. Break up long tasks. If a script runs before the LCP element has been painted on the screen the main thread will be blocked and the LCP element will not be painted on the screen. That is why it is a great practice to break up code that rungs for long into smaller, more manageable pieces that will 'yield to the main thread'.
  4. Pre-render your content. If your site runs on a JavaScript framework like REACT or Angular consider server side rendering. This will serve a pre-rendered page to the browser. If done correctly the Browser will show the pre-rendered version before if executes the frameworks JavaScript (hydration)

I help teams pass the Core Web Vitals:

lighthouse 100 score

A slow website is likely to miss out on conversions and revenue. Nearly half of internet searchers don't wait three seconds for a page to load before going to another site. Ask yourself: "Is my site fast enough to convert visitors into customers?"

Fix & Identify Largest Contentful Paint (LCP) issuesCore Web Vitals Fix & Identify Largest Contentful Paint (LCP) issues