The LCP, or Largest Contentful Paint, is one of the three Core Web Vitals we are all familiar with. The LCP metric measures the time from when the user starts loading a page to when the largest text block or image is visible in the viewport.
To provide a good user experience, you should aim for an LCP of less than 2.5 seconds for at least 75% of all page views.
There are several factors that can affect how quickly a browser can render a webpage, and any delay in these will directly and significantly impact your LCP score. Let’s explore what makes up the LCP score and present several ways to improve this metric…
Please note that it is rare for a quick fix in a specific part of a page to significantly change the LCP score. To improve this metric, you need to address the entire loading process of the page and ensure that you are optimizing every step of this process.
How to Identify the LCP Element?
Before you can improve the LCP score, you first need to identify and isolate the element around which you want to perform the optimization.
You can find the LCP element of any page using Google’s speed testing tool. Enter the URL of the page in this tool and click “Analyze.”
After PageSpeed presents the results report, scroll down to the section called “Diagnostics,” click on “Largest Contentful Paint element” and the LCP element of the page will be displayed:
As mentioned, the LCP element could be a specific headline, a text block, or in many cases, it could be a particular image.
As you can see, the LCP element in the page we tested above (the homepage of my site) is the <div class="hero_inner">
element and it’s even highlighted in yellow.
In the case of this site’s homepage, the LCP element is the specified
<div>
because it contains a background image.
Identifying the LCP element of the page allows us to implement the right optimization tactics to improve the LCP score. You might have noticed in the image above that PageSpeed also provides a table with information on how your LCP score is calculated. In the next section, we’ll discuss how to understand and analyze this table…
Several Ways to Optimize the LCP Metric
To know how to improve the LCP score on your site, it’s important to understand (more or less) how this metric is calculated. Here is a table that describes in percentages each of the factors that affect the LCP score:
LCP sub-part | % of LCP |
---|---|
Time to first byte | ~40% |
Resource load delay | <10% |
Resource load duration | ~40% |
Element render delay | <10% |
TOTAL | 100% |
Let’s now explain how to optimize each of these factors. Note that we will present the recommendations in order of importance, so those that are likely to have the most significant impact on the LCP score will be shown first.
Although the Time to first byte has a significant impact on the LCP score, I will present it last. This is because website developers typically do not have much control over this metric. More on TTFB in the following post.
1. Eliminate Resource Load Delay
To improve this factor, we must ensure that the LCP resource begins to load as early as possible. A rule of thumb in this case is to ensure that this resource starts loading at the same time as the first resource on the page.
The LCP resource in the can be either an image or some block of text using a web font.
So for our purposes, if the LCP resource starts loading at a certain time after the first asset on the site (First Resource) has loaded, then there is room for improvement. The following images can explain this well. The first one depicts a situation where there is room to improve the Resource Load Delay:
We want to get as close as possible to the next situation where the LCP resource starts loading together with the first loaded file, namely with the CSS file marked in this case:
To ensure that the LCP resource loading as quickly as possible, you need to make sure that the browser identify this asset immediately after the initial HTML response (i.e., after the blue line in the image called Document).
For example, if the LCP element on your site is a block of text using a particular web font, you need to ensure that the browser discovers and loads this font in the HTML Markup as early as possible, by loading the font in the <head>
of the site using <link rel="preload">
.
Take a look at the following post for more information on preloading assets using Preload Preload assets in advance.
Also, if the LCP element is an <img>
, you must use <link rel="preload">
and ensure that the browser discovers this image as early as possible in HTML.
In cases where the reference to the LCP element is made from an external CSS or JavaScript file, for example, a situation where the element in question has a background image which is defined in an external CSS file, you will also need to load that image using <link rel="preload">
but in this case with a high fetchpriority as in the following example:
<!-- Load the stylesheet that will reference the LCP image. -->
<link rel="stylesheet" href="/path/styles.css">
<!-- Preload the LCP image with a high fetchpriority so it starts loading with the stylesheet. -->
<link rel="preload" fetchpriority="high" as="image" href="/path/to/hero-image.webp" type="image/webp">
Be aware! Ensure that these images are not loaded lazily.
And one last tip for this section – if there are images in the critical top part of the screen that are loaded early but are not displayed immediately to the user (for example, in carousel cases) – it would be wise to add the fetchpriority="low"
attribute to the <img>
element in these images.
2. Eliminate Element Render Delay
The goal at this step is to ensure that the LCP element can be displayed to the user immediately after its resource has loaded. The main reason the LCP element can be delayed in its display is due to the browser’s rendering process being blocked for some reason:
- The page’s rendering process is blocked due to CSS files or non-asynchronous scripts in the
<head>
of the page. - The relevant LCP resource has finished loading, but the LCP element has not yet been added to the DOM because it is waiting for some JavaScript code to load.
- The element is hidden by some code (for example, in A/B Testing scenarios).
- The main thread is blocked due to long JavaScript tasks.
In the next part, we will describe how to address most of the issues that cause Element Render Delay.
A. Reduce or inline Render-Blocking Stylesheets
CSS files loaded from the HTML Markup will block the rendering of all content that follows them (which is positive since you do not want to display HTML without styling).
However, if the CSS file is large and takes significantly longer to load than the LCP resource, it will delay the rendering of the LCP element, even in situations where the resource has already finished loading.
This might be a bit confusing, but the following image will clarify:
To address this, the following actions can be taken:
- Inline the CSS in the HTML.
- Reduce the weight of the CSS file.
It is important to understand that inlining CSS is recommended only when the weight of the CSS file is small because inline content in HTML does not benefit from the advantages of caching on return visits.
In most cases, the best way to prevent a CSS file from blocking the rendering of the page is to reduce the file size so that the time it takes to load this file is less than the time it takes to load the LCP asset.
Here are some recommendations in this context:
- Remove unnecessary CSS from the file – Use Chrome Dev Tools to find CSS rules that are not used or that can potentially delay their loading.
- Delay loading non-critical CSS – Try to split CSS files and differentiate between CSS rules needed for the initial page load and those that can be loaded later (lazy load).
- Minify and compress the CSS file – It is advisable to reduce the size and transfer time of all CSS files, whether they are critical or not.
B. Defer or inline render-blocking JavaScript
In rare cases only, it is necessary to insert non-asynchronous scripts (without the defer
or async
value) in the <head>
of website pages. Any other situation will certainly have a negative impact on performance.
In cases where you need to load JavaScript code as early as possible, It would be wise to insert it as an inline script so that its processing (rendering process) is not delayed.
As for stylesheets, Also in the case of JavaScript you should use inline scripts only if it is very small javascript code.
C. Break up long tasks
Be aware, even in cases where JavaScript code does not delay processing or is not responsible for loading any elements, it can still delay the LCP. This situation usually occurs when the page loads particularly large JavaScript files, which need to be parsed and executed on the browser’s main thread.
In this case, even if the image, for example, has fully downloaded, its processing and display will still be delayed until a certain script completes its execution.
Modern browsers load images on the browser’s main thread, so if it is busy with other tasks, it will lead to unnecessary delays in processing the LCP element.
3. Reduce Resource Load Duration
The goal in this part is to actually reduce the time it takes to transfer any asset from the network to the user’s browser. Generally, there are several ways to do this:
- Reduce the size of the resource.
- Reduce the distance the resource has to travel.
- Reduce contention for network bandwidth.
- Eliminate the network time entirely.
We will briefly explain each of these actions:
A. Reduce Asset Size
As mentioned, the LCP asset of a page will be one of the following: either it will be a picture or it will be a specific text block directly affected by the loading time of a particular font.
The following points and guides will help you understand how to reduce the size/weight of these:
- It goes without saying that you should ensure the image is in the correct size and has been optimized.
- Use a modern image format like webp, for example.
- In the case of fonts, it’s preferable that these are loaded locally from your server.
- Optimize fonts by creating a subset (post on this coming soon).
B. Reduce the Distance the Asset Has to Travel
In addition to reducing the size of assets, you can also reduce the load times by getting your servers as geographically close to your users as possible. The best way to do this, of course, is by using a Content Delivery Network (CDN).
C. Eliminate contention for network bandwidth
Even if you have reduced the size and geographic distance, it’s possible that the LCP asset may take a long time to load if you are trying to load many assets simultaneously.
If you have set the LCP asset as a high priority using fetchpriority
, the browser will do its best to prevent a situation where it competes with less important assets for the critical upper part of the page. However, if there are many assets with high fetchpriority
or if you are loading many assets in general, this could affect the speed at which the LCP asset is loaded.
D. Completely Eliminate the Time Required to Load the Asset
The best way to reduce the loading time of assets is to completely eliminate the need to access the network/server to load these assets.
If you are loading assets with effective cache-control
settings, those assets will be served to users who have already visited your site once from the cache, which completely eliminates that resource load duration we previously discussed.
If your LCP asset is a web font, beyond the option to reduce the font size, you might want to consider whether you want the font to be considered a loading-blocking asset. If you set the font-display property with any value other than block
or auto
, then the text will always appear during loading and the LCP will not be delayed.
Be aware, your decision regarding the value of font-display will have an impact on the Visual Stability (CLS) in Core Web Vitals.
4. Reduce Time to First Byte (TTFB)
The goal in this part is to serve the initial HTML as quickly as possible. Time to first byte has a significant impact on the LCP score specifically and on the page loading time in general, as it directly affects each of the steps that follow.
Nothing can progress before the server serves the first byte of content, so any improvement in TTFB is likely to improve every other metric in Core Web Vitals.
By the way, a strong and high-quality hosting server has a significant impact on the first byte time specifically and on the LCP score in general. I’ve written a detailed post about what TTFB is and how to improve it on sites. Check it out…
Summary
Understanding and improving the LCP score on sites can be complex, and the timing of this metric is influenced by several factors. But if you treat the optimization of the LCP as the optimization of the specific LCP element, it might simplify things.
At a glance, the optimization of the LCP score can be summarized in four main points:
- Ensure the LCP asset is loaded as early as possible.
- Ensure that the LCP element can be processed and displayed immediately after its asset has finished loading.
- Reduce the loading time of the LCP asset as much as possible.
- Ensure that the server delivers the initial HTML as quickly as possible.
If you carry out these actions, be assured that you are providing an optimal user experience to visitors in this regard, and in this case, you will quickly find that your site’s LCP score is improving accordingly.