Optimize the Largest Contentful Paint Image
A step by step LCP Image Optimization guide
Optimize the Largest Contentful Paint Image
According to Google only 65% of all the pageviews on the internet (and that includes desktop as well as mobile) have a 'good' Largest Contentful Paint Score. That means 35% of the pageviews are failing and that is in-part because of mistakes made with images. This article breaks down common good practice patterns and mistakes when images become the Largest Contentful Paint element.
LCP tip: If you really want to master all the nuances of the Largest Contentful Paint and not just the Image optimization part, check out my Largest Contentful Paint section. It breaks down how to optimize the four key components:
- Time to first byte - The time the browser needs to wait for the html. This usually mostly consists of waiting for the server but also includes redirects, connection time, encryption etc.
- Load delay - The gap between when the LCP element could have started loading and when it actually does.
- Resource load time - The time it takes for the LCP resource to load. Optimizing compression and minification can speed this up.
- Render delay - Even with optimized resources, the browser might be tied up with other tasks (usually downloading stylesheets or heavy JavaScript processing), delaying the LCP rendering.
While all these factors matter, if your LCP element is an image (and it frequently is!), there are straightforward steps you can take to make sure it loads as fast as possible!
Experiments with the Largest Contentful Paint
I always say: listen and learn but don't take anyone their word. There are too many 'guru's' out there preaching wrong information. That is why I have created a fully automatic LCP experiment where you can check out for yourself what happens when the LCP element is not loaded optimally. Check out my LCP Test on github or try the live demo!
It will automatically test multiple LCP scenario's for you and show you the results. I will discuss those scenario's below and explain how and why it will speed up or slow down the LCP image element.
1. Do not use an image
The fastest way to improve your image-based Largest Contentful Paint? Don’t use an image! Wait, what? Yep, you heard me right. Let me explain.
Take a look at this RUM breakdown of LCP element types. A you can see text-based LCP element are just a lot faster and they even make up the majority of LCP elements!
So what's the case for images versus text? Images are important, they make your site visually appealing. But Core Web Vitals does not care which element becomes the LCP. When the LCP element is a text based element it usually co-occurs with the First Contentful Paint.
So should you switch to a text based Largest Contentful Paint element? That depends! Images matter and they make your site visually appealing. That means you will not hear me advocate for switching to old boring text elements. But mistakes also happen! I had a dollar for every category page that "forgot" to add a descriptive category text and accidentally made a lazy-loaded product image the LCP, delaying load times by 2 seconds, I’d be on a nice vacation by now.
2. Use the fastest image format available
Without getting into a heated debate about squeezing out the last byte or the perfect settings for WebP vs. AVIF, let’s agree on one thing: older formats like JPEG and PNG are largen and slower compared to modern formats like WebP or AVIF. If you want a deeper dive, this article breaks it down.
As a general rule, you should serve a lossy WebP or AVIF version of your LCP image (better yet, use these formats for all your images, but we’re focusing on LCP here). With WebP support at around 95% and AVIF support at 92%, it sstill makes sense to serve older, fallback images as well. To do this just 'progressive enhancements' where we serve these modern formats only to browsers that support them.
Using the <picture> element: The <picture>
element allows browsers to skip unsupported image formats, selecting the first one they can handle. Here’s how to do it:
<picture>
<source srcset="img.avif" type="image/avif">
<source srcset="img.webp" type="image/webp">
<img src="img.jpg" alt="Image" width="123" height="123">
</picture>
Using content negotiation: Content negotiation lets your server serve different image formats based on browser support. Browsers announce supported formats via the Accept header. For instance, in Chrome, the Accept header for images looks like this:
Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8
Then, on the server side, read the accept header and based on the header serve the 'best format'
3. Use responsive images
When it comes to optimizing LCP images, size really does matter. One of the easiest wins is serving images with the smallest possible dimensions that still look good on your users' screens. Large images serve no function at all: they waste bandwidth & slow down load times, especially for users on slower connections or mobile devices.
To ensure you’re not wasting pixels, follow these steps:
Responsive Images:
Use the srcset attribute to serve different image sizes based on the user's device. This way, smaller devices get smaller images, which helps speed up the LCP.
<img
src="img.jpg"
srcset="img-400px.jpg 400w, img-800px.jpg 800w, img-1200px.jpg 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1200px"
alt="Image" width="123" height="123">
4. Scale your images to the screen size!
Avoid serving images that are larger than necessary. If the LCP element is only 600px wide in the viewport, make sure the image is no larger than that. Trust me, I see this happening every day! To check just do this: inspect the image by right clicking the image and select 'inspect-element'. You will now see the dev-tools and the image html is highlighted with a blue background. You can now see the image renderend size (443 x 139px) is much smaller then the intrinsic image width (1090x343px). That is almost 3 times as large and resizing the image could have saved at least 50 of the file size
5. Use eager loaded LCP images
To get the best performance out of your LCP, you should eagerly load visible the LCP element (and lazy load images that aren’t immediately visible).
Eager Loading: The LCP element (usually above-the-fold content) should always be loaded eagerly. This ensures it appears as quickly as possible, reducing the time it takes for your Largest Contentful Paint to render. By default, images load eagerly unless specified otherwise, but double-check that you haven't set loading="lazy" on the LCP image. Doing so can significantly delay the LCP and hurt your Core Web Vitals score.
Geek alert: lazy images are not enqueued by the preload scanner. The preload scanner is a super fast secondary html scanner that enqueues important resources immediately. When the preload scanner is bypassed the browser will have to wait for the rendering engine to complete before it enqueues 'visible images'
<img src="lcp-image.jpg" alt="Main image" width="800" height="400">
For images that appear below the fold (those not visible when the page first loads), lazy loading is the way to go. By delaying the loading of these images until the user scrolls near them, you free up bandwidth for more important content, like your LCP element. In this way lazy loading is a double edged knife: If used correctly it will speed up your LCP content, if used incoprreclty it will slow it down!.
<img src="non-visible-image.jpg"
alt="Secondary image"
loading="lazy"
width="800" height="400">
The balance? Eagerly load the critical content (like your LCP image) and lazy load less critical resources and below the fold images!
6. Preload the LCP Image
Preloading the Largest Contentful Paint (LCP) image is one of the easiest ways to speed up its appearance on the page. It tells the browser to prioritize loading this image, ensuring it’s ready as soon as possible.
Why Preload the LCP Image?
When the browser loads a page, it processes the HTML, stylesheets, and scripts in a certain order. Sometimes, the LCP image is referenced further down the chain, meaning the browser gets to it later than it should. Preloading the LCP image lets the browser know upfront that this image is critical and should be loaded immediately, reducing the delay in rendering your largest element.
How to Preload the LCP Image
By using the <link rel="preload"> tag, you can make sure the browser starts fetching the LCP image as early as possible in the loading process.
<link rel="preload" href="lcp-image.jpg" as="image" type="image/jpeg">
This ensures that the LCP image is in the browser’s queue from the start, avoiding the wait that often occurs if the image is buried in CSS or scripts.
Remember: Only preload the LCP image, as preloading too many resources can overwhelm the browser and hurt performance. Stick to what matters most for your Core Web Vitals.
7. Remove fade-in animations from the LCP Image
Fade-in animations can be visually appealing, but when it comes to your Largest Contentful Paint, they’re a hidden bottleneck. If the LCP element (often an image) uses a fade-in effect, the browser won’t count the LCP until the animation finishes. This delays the LCP timing and can significantly hurt your performance metrics.
LCP Timing Happens After the Animation Ends: The browser considers the LCP complete only when the element is fully visible. If you have a fade-in animation, the timer keeps running until the image or content has completely faded in, which can easily add extra seconds to your LCP score.
Keep It Simple: To ensure the LCP element appears as quickly as possible, avoid using fade-in effects. Let the image load and display immediately, without any transition or animation.
By skipping fade-ins on the LCP image, you’ll prevent unnecessary delays and improve your Core Web Vitals, ensuring a faster, smoother experience for users.
8. Self-Host the LCP Element
To get the best performance out of your Largest Contentful Paint, you should always consider self-hosting the LCP element, especially if it's an image or other critical resource. Relying on third-party servers can introduce delays that are completely outside of your control, which can hurt your LCP and overall page performance.
Think of it like this: Not self-hosting your LCP element is like constantly borrowing sugar from your neighbor. Every time, you have to walk over, wait at the door, and hope they are home. Relying on a third-party server for your LCP makes your website wait for that external resource, slowing down load times. Self-hosting is like keeping the sugar in your kitchen: "fast, direct, and reliable".
Reduce External Dependencies: When your LCP element (like an image) is hosted on a third-party server, you’re at the mercy of that server's speed, availability, and any additional round-trip times (RTT). Self-hosting eliminates this uncertainty, allowing you to serve the image directly from your own server, ensuring faster and more reliable delivery.
Leverage Caching and Optimizations: By self-hosting, you can take full advantage of caching strategies and serve the image from the closest server to the user, especially if you're using a CDN. This reduces the time it takes to load the LCP element, resulting in faster rendering.
Control Over Image Optimization: Self-hosting gives you control over how the image is optimized, whether it’s compression, resizing, or format selection—without relying on third-party handling. This way, you can ensure the image is perfectly tailored for fast loading.t
9. Avoid Client-Side Rendering for the LCP Element
Client-side rendering (CSR) can be a major hindrance when it comes to optimizing your Largest Contentful Paint. If your LCP element (usually a large image, text block, or video) is rendered on the client side via JavaScript, it often leads to slower LCP times as the browser has to wait for scripts to download, parse, and execute before displaying the critical content.
Delays in Rendering: With CSR, the LCP element is only displayed after the browser processes JavaScript, which can significantly delay its appearance. The longer this takes, the worse your LCP score becomes. Every extra second spent processing scripts translates into a longer wait for your users to see the most important content.
Switch to Server-Side Rendering (SSR) or Static Rendering: By rendering the LCP element server-side or as part of a static HTML response, you allow the browser to load and display it immediately, without waiting for JavaScript to kick in. This drastically improves LCP timing, as the browser can render the LCP element right away when it starts loading the HTML.
Minimize JavaScript on Critical Path: If you can’t avoid some client-side scripts, make sure they don’t block the LCP element from rendering. Defer or async non-critical scripts to prevent them from delaying the appearance of your LCP.
Need your site lightning fast?
Join 500+ sites that now load faster and excel in Core Web Vitals.
- Fast on 1 or 2 sprints.
- 17+ years experience & over 500 fast sites
- Get fast and stay fast!