Optimize Large Contentful Paint (LCP)

The most common causes of a poor LCP are:

  1. Slow server response times
  2. Render-blocking JavaScript and CSS
  3. Slow resource load times
  4. Client-side rendering

The LCP score can be analysed as following.

  • Good<= 2.5s (2.5 seconds or less)
  • Needs improvement> 2.5s <= 4s (between 2.5 and 4 seconds)
  • Poor> 4s (more than 4 seconds)

For slow server response times

  • Use caching and optimized server to improve this.
  • Consider using Caching or CDN services such as cloudflare.
  • Try to keep the initial server response under 1s to get good performance scores.

For render blocking JavaScript and CSS

  • Minify CSS
  • Remove unwanted CSS, by creating multiple stylesheets and loading only required CSS files for the given page.
  • CSS and Javascripts that are loaded synchronously will be render blocking. Consider loading critical CSS first, using inline <style> tag and other not so important styles can be deferred by loading them later in the dom. 
  • For the non-critical CSS, you can use loadCSS to load them asynchronous. 

For slow resource load times

The time it takes to load these elements if rendered above-the-fold will have a direct effect on LCP. There are a few ways to ensure these files are loaded as fast as possible:

  • Lazy load images, iframe, embeds etc.
    • Can use loading=”lazy” attribute for image tags or use some JS library that does the same thing. 
  • Optimize and compress images
    • Consider not using an image in the first place. If it’s not relevant to the content, remove it.
    • Compress images
    • Convert images into newer formats (JPEG 2000, JPEG XR, or WebP)
    • Use responsive images (srcset attribute to add more image sizes as per device screen size)
    • Consider using an image CDN
  • Preload important resources
    • Some assets such as fonts, images, are somewhere deep in CSS, and that may load later as per the loading sequence.
    • If you know that a particular resource should be prioritized, use <link rel=”preload”> to fetch it sooner. Many types of resources can be preloaded, but you should first focus on preloading critical assets, such as fonts, above-the-fold images or videos, and critical-path CSS or JavaScript.
<link rel=”preload” as=”script” href=”script.js” /><link rel=”preload” as=”style” href=”style.css” /><link rel=”preload” as=”image” href=”img.png” /><link rel=”preload” as=”video” href=”vid.webm” type=”video/webm” /><link rel=”preload” href=”font.woff2″ as=”font” type=”font/woff2″ crossorigin />
  • Compress text files
    • First, check if your server already compresses files automatically. Most hosting platforms, CDNs, and reverse proxy servers either encode assets with compression by default or allow you to easily configure them.

Cloudflare.com is one such service you can use.

  • Deliver different assets based on network connection (adaptive serving)
    • If you have large assets that are critical for initial rendering, you can use different variations of the same resource depending on the user’s connection or device. For example, you can display an image instead of a video for any connection speeds lower than 4G:
if (navigator.connection && navigator.connection.effectiveType) { if (navigator.connection.effectiveType === ‘4g’) {   // Load video } else {   // Load image }}
  • Cache assets using a service worker
    • Service workers can be used for many useful tasks, including serving smaller HTML responses as mentioned earlier in this article. They can also be used to cache any static resource which can be served to the browser instead of from the network on repeat requests.

Precaching critical resources using a service worker can reduce their load times significantly, especially for users who reload the web page with a weaker connection (or even access it offline). Libraries like Workbox can make the process of updating precached assets easier than writing a custom service worker to handle this yourself.