Lazy loading images diagram showing above-fold eager loading vs below-fold lazy loading and LCP impact
Web Performance

Lazy Loading Images — SEO Impact and Implementation Guide

Sunny Pal Singh · · 6 min read

Lazy loading defers image loading until an image is about to enter the viewport — reducing initial page weight and improving load times. Implemented correctly, it helps Core Web Vitals. Implemented incorrectly (particularly on the LCP image), it's one of the most common causes of poor Largest Contentful Paint scores. This guide covers when to use lazy loading, what to exclude, and how to implement it without harming rankings.

Most page speed guides say the same thing: add loading="lazy" to your images and watch your scores improve. That advice is correct for below-fold images — and completely wrong for the one image that matters most to Google: the LCP image.

Lazy loading is a net positive when applied carefully. The problem is that CMSs and themes routinely apply it globally to every <img> tag on the page — including the hero image that sits at the top of every article. That single misconfiguration is responsible for more LCP regressions than almost any other implementation mistake. This guide covers the full picture: what lazy loading does, where the line is, and how to verify your implementation isn't hurting Core Web Vitals.

Key Takeaways

  • loading="lazy" on below-fold images reduces initial bandwidth and speeds up TTFB and FCP — beneficial for SEO
  • NEVER apply loading="lazy" to the LCP image (usually the hero/header image) — it delays the largest element's load and directly worsens LCP
  • NEVER apply loading="lazy" to images with fetchpriority="high" — the attributes conflict and LCP candidates need eager loading
  • Google's crawler can execute JavaScript lazy loading but native loading="lazy" is safer and more predictable for crawlers
  • Always include width and height attributes on lazy-loaded images — without them, the browser can't reserve space and layout shifts occur (CLS)

What Lazy Loading Does

Without lazy loading, the browser fetches all images in the HTML as soon as they're discovered — even images 2,000px below the viewport that the user may never scroll to. This inflates initial page weight and competes for bandwidth with critical resources like the render-blocking CSS and the LCP image.

With loading="lazy", the browser only fetches images when they're close to entering the viewport (the threshold is browser-defined, typically around 1,000px on desktop). Below-fold images load on scroll instead of on page load. This frees up early bandwidth for the resources that matter for First Contentful Paint and Largest Contentful Paint.

Browser support is now universal. loading="lazy" is natively supported in Chrome, Firefox, Safari, and Edge. No JavaScript library is needed for new implementations — native is both simpler and more reliable.

The LCP Exception — Never Lazy-Load This Image

The LCP image is the largest visible element when the page loads — typically the hero image, banner, or featured image at the top of the page. It is the element Google's Core Web Vitals algorithm measures for Largest Contentful Paint.

Applying loading="lazy" to the LCP image defers its fetch. The browser won't request the image until it enters the viewport — but on initial load, it already is in the viewport. The defer still introduces a delay relative to eager loading, because the browser has to finish its initial layout pass before it begins fetching lazy images. The result is a directly higher LCP time.

How to identify your LCP image: run the Page Speed Inspector. The LCP candidate URL is reported in the HTML analysis section alongside timing data.

Correct implementation for a page with a hero image:

<!-- LCP hero image — eager loading + high fetch priority -->
<img src="/hero.jpg" alt="Hero" width="1200" height="600"
     loading="eager" fetchpriority="high">

<!-- Below-fold product images — lazy load these -->
<img src="/product-1.jpg" alt="Product 1" width="400" height="400"
     loading="lazy">

The fetchpriority="high" attribute tells the browser to fetch this image early in the resource queue, before lower-priority resources. Combined with loading="eager", this is the optimal setup for any LCP candidate.

Which Images to Lazy Load

Apply loading="lazy" to:

  • Images below the fold that are not visible on initial page load
  • Images in product grids, content lists, or carousels that extend below the viewport
  • Thumbnails in "related posts" or "you may also like" sections
  • Author avatars and comment thread images
  • Footer images and decorative below-fold graphics

Do NOT apply loading="lazy" to:

  • The LCP image — the hero, banner, or first large image visible on page load
  • Images with fetchpriority="high" — these are LCP candidates by definition
  • Images that are always above the fold regardless of device size
  • Brand logos and navigation images in the header
  • Open Graph images — these are metadata, not rendered in the page

The practical rule: if the image is visible when the page first loads on a typical mobile device, do not lazy-load it.

Width and Height — Required With Lazy Loading

Without width and height attributes, the browser doesn't know how much vertical space to reserve for an image before it loads. When the image finally loads on scroll, it pushes content downward — causing Cumulative Layout Shift (CLS), which is the third Core Web Vitals metric.

Always include dimensions on lazy-loaded images:

<!-- Bad — no dimensions, causes CLS when lazy image loads -->
<img src="/photo.jpg" alt="Photo" loading="lazy">

<!-- Good — browser reserves space via aspect ratio, no CLS -->
<img src="/photo.jpg" alt="Photo" width="800" height="600" loading="lazy">

For responsive images (where actual render size varies with the viewport), include the natural dimensions of the source image. The browser uses the aspect ratio derived from those values to maintain the correct layout space even as the rendered size scales with CSS.

If you're using CSS to make an image responsive (max-width: 100%; height: auto), the HTML width and height attributes still serve a purpose — they give the browser the aspect ratio before the image loads, allowing it to allocate space without CLS. Do not omit them just because you have responsive CSS.

JavaScript Lazy Loading vs Native

Before loading="lazy" had broad browser support, JavaScript libraries were the standard approach. Libraries like lazysizes and lozad.js work by replacing the src attribute with data-src, then swapping to the real URL when the element enters the viewport via an IntersectionObserver.

The problem for SEO: Google's crawler renders JavaScript but does so asynchronously and with a delay. Images loaded via JS lazy loaders may be fetched during the render phase, but the timing is less predictable than native loading="lazy". In some crawl configurations, JS-deferred images may be missed entirely or indexed with lower confidence.

Additionally, JS lazy loaders often set the initial src to a 1x1 transparent placeholder GIF. If Google indexes the page before completing JavaScript rendering, it sees placeholder images rather than your actual content. This matters for image search indexing and for pages where images are core content (e-commerce product pages, recipe photos, portfolio work).

Recommendation: use native loading="lazy" for all new implementations. For existing sites using JS lazy loaders, migrating to native lazy loading is straightforward and the reliability improvement is measurable. Only retain a JS library if you need IE11 support, which is near-zero in 2026.

Detecting Lazy Loading Issues

The Page Speed Inspector reports several lazy loading signals that are directly relevant to Core Web Vitals:

  • LCP candidate URL — the specific image identified as the largest visible element; check whether it has loading="lazy" applied
  • Images without width/height attributes — each one is a CLS risk whenever it lazy-loads and shifts layout
  • Images potentially above the fold — images near the top of the HTML that may be in the initial viewport but have lazy loading applied
  • Images with fetchpriority="high" and loading="lazy" — a direct conflict that the inspector flags as a misconfiguration

Running the inspector on any page gives you the LCP candidate URL. Cross-reference that URL against your HTML — if it has loading="lazy", that is the source of your LCP regression.

The most common lazy loading mistake: A CMS or theme applies loading="lazy" to all images site-wide, including the first hero image. Check your LCP image specifically — it should have loading="eager" or no loading attribute at all. WordPress's default image blocks added loading="lazy" globally in version 5.5 without LCP awareness; many themes still ship with this behaviour.

Preloading the LCP Image

For the highest LCP scores, go beyond loading="eager" and add a <link rel="preload"> in the <head>. This instructs the browser to fetch the LCP image even before it encounters the <img> tag in the HTML body — typically the single largest single improvement available for LCP:

<!-- In <head>: preload the LCP image -->
<link rel="preload" as="image" href="/hero.jpg"
      fetchpriority="high">

<!-- In <body>: the img tag itself -->
<img src="/hero.jpg" alt="Hero" width="1200" height="600"
     loading="eager" fetchpriority="high">

For responsive images using srcset, use imagesrcset and imagesizes on the preload link to match the correct source:

<link rel="preload" as="image"
      imagesrcset="/hero-400.jpg 400w, /hero-800.jpg 800w, /hero-1200.jpg 1200w"
      imagesizes="(max-width: 600px) 400px, (max-width: 1000px) 800px, 1200px"
      fetchpriority="high">

Preloading the LCP image is one of the recommendations the Page Speed Inspector surfaces when it detects a large above-fold image without a corresponding preload hint.

Check Your LCP Image and Lazy Loading Setup

Free, no signup. The Page Speed Inspector identifies your LCP candidate image, flags images missing width/height attributes, and reports any lazy-loading issues that are hurting Core Web Vitals.

Try the Page Speed Inspector Free →
SP

Sunny Pal Singh

Fellow · Technical Director — AI Infrastructure, Cloud Orchestration & Network Automation

Sunny is a Fellow and Technical Director specialising in AI infrastructure, cloud orchestration, and network automation. With hands-on depth across AWS, Azure, GCP, Red Hat OpenStack, and OpenShift, he leads high-performing teams of architects and engineers building transformative solutions at scale. He built ByteWaveNetwork to bring the same engineering rigour to everyday web tooling.

Affiliate disclosure: Some links on this page may be affiliate links. We only mention tools we've personally used and have an honest opinion about. Affiliate revenue helps keep ByteWaveNetwork's tools free and maintained. We are not paid by any of the tools compared in this article for favorable coverage.

Choose design