Lazy Loading Images for SEO: Defer Images Without Hiding Them

Crawvix Editorial Team · Published October 29, 2026 · Last updated October 29, 2026 · 8 min read

Images are often the heaviest part of a page. Lazy loading postpones the download of images until the visitor is about to see them, so the browser does not spend time and data on pictures far down the page. Done well, it makes pages lighter. Done badly, it delays the most important image on the page or hides images from search engines altogether.

This guide covers lazy loading SEO for site owners and developers: how to use the browser's built-in loading attribute, which images you should never lazy-load, how Google treats lazy-loaded content, and how to test the result. You will end with a short rule for every image on your pages and proof that Google can still see them.

Lazy loading is a tool for reducing unnecessary downloads. It does not make an image rank, and a faster page is not assured by it alone.

Before you begin

  • Access: you can edit your page templates, theme or CMS image settings. Many CMS platforms and themes lazy-load automatically, so find out what yours already does before adding anything.
  • Tools: a browser with developer tools, access to Google Search Console for the URL Inspection tool, and optionally Lighthouse.
  • Time and risk: an hour for a template change. The risk is low, but lazy-loading the wrong image can slow the page, so test before and after.
  • Back up your templates and note which pages are most important, such as the home page and your top landing pages.

How lazy loading works and why SEO cares

With the native approach, you add loading="lazy" to an <img> element. The browser then defers loading the file until it is within a calculated distance of the viewport. The default value, eager, loads the image no matter where it sits on the page.

For search, there are two concerns.

First, can Google see the image? Google's lazy-loading guidance says lazy loading can hide content if it is done incorrectly. Googlebot does not interact with your page, so anything that waits for a scroll event or a click may never load. Google lists methods that work without user actions: built-in browser lazy loading for images and iframes, the IntersectionObserver API (with a polyfill if needed), and libraries that load content when it enters the viewport. It also says image and video URLs should appear in the src attributes of <img> and <video> elements, which you can check with the URL Inspection tool.

Second, does it slow down the page? Google's advice is not to lazy-load content that users see immediately, because it slows loading. Web.dev adds that you should not lazy-load images likely to be in the viewport when the page loads, especially the Largest Contentful Paint (LCP) image.

Step-by-step instructions

Step 1: List the images on a page and sort them

Open a key page and list every image: logo, hero, product photos, thumbnails, icons, footer logos. Sort them into two groups:

  • Above the fold: visible without scrolling on common screen sizes, including the likely LCP image. These load normally.
  • Below the fold: only visible after scrolling. These are candidates for lazy loading.

Why: the cost of getting it wrong is highest for the first group. If you are unsure which element is the LCP, browser developer tools and Lighthouse can show you. Our LCP guide explains how to find and improve it.

You have succeeded when each image on the page is marked "load now" or "defer".

Step 2: Add the loading attribute to below-the-fold images

For images you want to defer, use the native attribute with width and height set:

<img src="/img/team-photo.jpg"
     alt="Five members of the support team at a table"
     width="800" height="533"
     loading="lazy">

Web.dev recommends adding width and height to all <img> tags. Without them an image defaults to 0 by 0 pixels until it loads, which can cause layout shift when it appears. Matching dimensions reserve the space in advance. For more on layout shift see reducing Cumulative Layout Shift.

The attribute is supported in current versions of the major browsers. According to web.dev, image lazy loading arrived in Chrome 77, Edge 79, Firefox 75 and Safari 15.4. Where it is not supported the attribute is simply ignored and the image loads normally, so the failure mode is safe.

You have succeeded when below-the-fold images have loading="lazy" along with width and height.

Step 3: Keep above-the-fold images eager and give the LCP image priority

Do not add loading="lazy" to the logo, hero image or the LCP image. Leave the default, or set it explicitly:

<img src="/img/hero.jpg"
     alt="A volunteer planting a tree seedling"
     width="1200" height="630"
     loading="eager"
     fetchpriority="high">

Web.dev says fetchpriority="high" raises the priority of important images such as the LCP image. It also notes that combining loading="lazy" with fetchpriority="high" is generally unnecessary, because an off-screen image stays deferred anyway.

Be careful with automatic lazy loading from themes and plug-ins. Web.dev describes how a lazy-loading implementation that deferred above-the-fold images on WordPress pages hurt LCP, and how limiting lazy loading to below-the-fold images reversed that. Check what your platform does to the first image on the page.

You have succeeded when the first, large image on each page is not lazy-loaded.

Step 4: Use IntersectionObserver only when you need custom behaviour

If you must use a script-based loader, for instance to support a background-image carousel, make sure the loader reacts to visibility and not to user input. Google lists IntersectionObserver as an acceptable approach:

const observer = new IntersectionObserver((entries, obs) => {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      obs.unobserve(img);
    }
  });
});

document.querySelectorAll("img[data-src]").forEach((img) => observer.observe(img));

This pattern keeps the real image address in data-src until the image is near view, and only then sets src. That is the part that needs testing, because Google's guidance wants image URLs in src attributes in the rendered HTML. Verify it in Step 6. When the native attribute meets your needs, prefer it, since it needs no script.

You have succeeded when the loader fires on visibility alone and the real image URL ends up in src in the rendered page.

Step 5: Handle iframes and paginated content separately

Browsers also support loading="lazy" on <iframe> elements. Web.dev says it uses the same attribute and has been standardised. Embedded videos and maps are good candidates, and the guide to lazy-loading iframes and video embeds covers them.

For lists that load more items as you scroll, Google's advice is to give each chunk its own persistent, unique URL, keep each URL's content the same on every load (using absolute page numbers such as ?page=12 rather than relative parameters), link the pages sequentially and update the address with the History API. Without real links, Googlebot will not reach the later items. See infinite scroll SEO.

You have succeeded when each chunk of a long list can be reached by a link to a unique URL.

Step 6: Test what Google sees

  1. In Search Console, open the URL Inspection tool, inspect the page and run the live test.
  2. Open the rendered HTML and search for one of your below-the-fold images. Its URL should be in the src attribute of an <img> element.
  3. Check the screenshot and the list of loaded resources for the images that should be present.
  4. In a browser, open DevTools, switch to the Network tab with images filtered, load the page and scroll. Images should load as you approach them, and the LCP image should load right away.

You have succeeded when the rendered HTML contains every image you care about and the LCP image is not delayed.

Step 7: Measure before and after

Run Lighthouse or a field-data tool on the page before and after. A change in LCP or total page weight tells you whether the setup helps. Web.dev notes that part of its own evidence is correlational, and your site will differ, so test your own pages. Our Lighthouse performance guide covers reading the results, and WebP and AVIF images covers making each file smaller.

You have succeeded when you can state whether LCP and page weight improved, stayed the same or got worse.

Final verification checklist

  • Below-the-fold images use loading="lazy" and have width and height.
  • The logo, hero and LCP image are not lazy-loaded.
  • Important images have real URLs in src (or srcset) in the rendered HTML.
  • URL Inspection shows the images you care about.
  • Image loading does not depend on scrolling events, clicks or hover.
  • Infinite-scroll lists have unique, linked URLs for each chunk.
  • LCP did not get worse after the change.
  • No layout shift appears when images load.

Common mistakes to avoid

  • Lazy-loading every image. This includes the hero. Leave above-the-fold images eager.
  • Missing width and height. Images then load into zero space and push the content around. Add the dimensions.
  • Loading on scroll events only. Googlebot does not scroll. Use visibility-based loading.
  • Hiding the real URL in a custom attribute. If the real address never reaches src in the rendered HTML, Google may not see it. Test it.
  • Assuming your theme does it right. Some themes lazy-load the first image. Check the page source.
  • Combining lazy loading with high priority. Web.dev calls this generally unnecessary. Choose one.
  • Skipping the test. Always run a live URL Inspection after changing how images load.

Frequently asked questions

Does lazy loading hurt SEO?

Not when implemented correctly. Google says lazy loading can hide content if done incorrectly, so use visibility-based methods and test with URL Inspection. Delaying the LCP image can slow the page, which is a performance concern.

How far from the viewport does the browser start loading?

The distance is not fixed by developers. Web.dev says it varies with image type and connection speed, is hard-coded in the browser, cannot be changed through the API and may change in the future. Do not build on a specific number.

Should I lazy-load background images?

The loading attribute applies to <img> and <iframe>. For other cases you need a script-based loader, with the cautions in Step 4. If an image matters for search, a real <img> element is the safer choice.

Do I need a polyfill for older browsers?

Without support the attribute is ignored and the image loads normally. A polyfill is only needed if you require deferred loading in those browsers. Web.dev shows a feature-detection check for that case.

Does lazy loading help Core Web Vitals?

It can reduce initial downloads, which may help. It can also hurt LCP if the wrong image is deferred. Measure on your own pages.

Load the first slide eagerly and defer the others. Make sure the later slides are reachable without interaction, or accept that they may not be seen, and check how Google renders the page.

Official references


Next step: See how Crawvix checks a website and capture a baseline once scanning opens. This guide provides technical information, not a guarantee of rankings, traffic or index inclusion.

In this category

All 25 Performance guides