LCP lazyloaded

This health check detects Largest Contentful Paint (LCP) elements that are incorrectly lazy-loaded based on real user data.

It identifies cases where the LCP element, typically an image, is delayed because it is marked for lazy loading instead of being prioritized.

Each todo represents a template where the LCP element is lazy-loaded for a specific device type.

About this check

When this check is triggered

You’ll see this check when:

  • The LCP element is an image
  • The image is marked as lazy-loaded (e.g. loading="lazy" or lazyload libraries)
  • The impact is visible in real user data (p75)
  • There are enough events to validate the pattern

What you’ll see

Each todo includes:

  • Template
  • Device type (desktop, mobile, tablet)
  • Confirmation that the LCP element is lazy-loaded

Example:

LCP is lazyloaded on product-page for mobile
On page template product-page for mobile, the LCP is an image and it is lazy loaded.

Why this matters

The LCP element is the most important visual element on the page.

When it is lazy-loaded:

  • The browser delays loading it
  • It is discovered too late in the loading process
  • LCP is significantly delayed

This directly impacts Core Web Vitals and perceived loading speed.

More context on web.dev and RUMvision LCP blogpost.

How to fix it

Most issues come from:

  • Using loading="lazy" on above-the-fold images
  • Applying lazyload libraries globally to all images
  • Depending on client side rendering
  • Not distinguishing between above- and below-the-fold content

Possible causes and fixes:

1. Do not lazy-load the LCP image

The LCP image should always load immediately.

What to check

Check for native lazyloaded images like this:

img src="hero.webp" loading="lazy"

What to do

Change it to loading=eager:

img src="hero.webp" loading="eager"

Or simply remove the attribute, which defaults to loading=eager

Important considerations

  • Do not allow too many images to be loaded eagerly, as that will result in resource competition which could delay the download of your most important (LCP candidate) image.
  • Even when it doesn't become your LCP candidate, never lazyload the biggest visible image within the initial viewport, as those have the highest chance of becoming an LCP candidate.

2. Avoid JavaScript-based lazyloading for above-the-fold images

What to check

  • Libraries adding classes like lazyload, lazyloaded or lazyautosizes
  • Image gallery libraries like owl carousel hiding the full gallery until all JavaScript is downloaded and executed

An example:

img data-src="hero.webp" class="lazyoad"

Why this matters

  • JS-based lazyloading delays image loading even further
  • Requires script execution before the image can load

What to do

  • Exclude above-the-fold images from lazyload logic
  • Only apply lazyloading to below-the-fold content
  • Force the first slide to be shown from the start instead of letting image gallery libraries hide it

3. Avoid delaying LCP discovery

The browser must discover the image early.

What to check

Aside from library-dependency, there can be other (third party script or framework) dependencies. Check for the following:

  • Images injected via JavaScript
  • Images hidden behind components or sliders
  • Delayed rendering of hero sections

What to do

  • Render LCP image in initial HTML
  • Avoid client-side injection for above-the-fold content

4. Preload the LCP image

Ensure the browser discovers the image as early as possible. In case of JavaScript dependency or chunked HTML as the result of large HTML documents, browsers typically aren't able to discover images in time.

What to do

Aid browsers by at least exposing the LCP candidate to the browser early in time. This can be achieved with a preload link early in the server side rendered HTML (or response headers).

An example:

link rel="preload" as="image" href="/hero.webp" type="image/webp"

Why this matters

  • Reduces discovery delay
  • Improves LCP timing

5. Ensure correct fetch priority

Eagerly loading LCP images won't change its priority. Aside from not using loading=lazy, it's a best practice to boost its priority. This can be achieved with the fetchpriority attribute. When it comes to images, limit its usage to only LCP candidates

What to do

img src="hero.webp" fetchpriority="high"

Why this matters

  • Signals that this image is critical
  • Helps the browser schedule it earlier

6. Optimize image delivery

Even when loaded correctly, the asset itself matters.

What to check

  • Image size and dimensions
  • Compression and format
  • Responsive image setup

What to do

  • Use modern formats (e.g. WebP, AVIF)
  • Serve responsive images with srcset
  • Ensure proper caching

Further debugging

How to approach this in RUMvision

  1. Open the todo
  2. Identify the template
  3. Inspect the LCP element:
    • Check if it has lazy-loading applied
  4. Verify in DevTools:
    • Network tab → when does the image start loading?
  5. Remove lazy loading and prioritize the image
  6. Monitor improvement over the next 7 days

Pro tip

Focus on:

  • Hero images
  • Banner images
  • Product images above the fold
  • Mobile layouts (often different LCP elements)

Fixing lazy-loaded LCP images is often one of the fastest wins for improving Core Web Vitals.