Lazy Loading Images: When and How to Use It

Offscreen images loading upfront waste data and requests. How to add native lazy loading safely without delaying the image that sets your LCP.

Updated

The short answer

Lazy loading tells the browser to wait before downloading an image until the visitor scrolls near it. Without it, every image on the page is requested upfront, even the ones far below the first screen, which costs visitors data and your server requests for images most people never see. The fix is native loading="lazy" on offscreen images, while the main image at the top of the page stays eager so your Largest Contentful Paint does not get slower.

What lazy loading is

Browsers support lazy loading natively with one attribute:

html
<img src="/gallery/photo-12.jpg" alt="Runner on a forest trail" width="800" height="533" loading="lazy">

With loading="lazy", the browser holds the request until the image is close to the viewport. Without it, or with loading="eager", the image is fetched as soon as the HTML is parsed:

html
<img src="/gallery/photo-12.jpg" alt="Runner on a forest trail">

On a long page with a gallery, product grid or blog feed, that can mean dozens of image requests before the visitor scrolls once.

Why it matters

  • Less data for visitors. People who never scroll to the bottom never download the bottom images. On mobile data that matters.
  • Fewer requests. Lower server and CDN costs per page view, and less competition on slow connections.
  • Modest speed gains. Browsers already give offscreen images a low priority, so lazy loading rarely makes the first screen much faster on its own. The big speed lever is the opposite one: making sure the main image is never lazy.
  • Not a ranking factor. The attribute itself does not lift rankings. Search crawlers do not scroll or click, so images must load without interaction. Native loading="lazy" meets that; script based loaders that wait for a scroll event may hide images from search.

The one image you should not lazy load

Lazy loading the image that is visible on the first screen makes the page slower, not faster. The browser waits until layout is calculated to decide whether the image is near the viewport, so the most important image starts downloading late. Lighthouse checks this in the LCP request discovery insight (formerly the Largest Contentful Paint image was lazily loaded audit), which also looks for fetchpriority="high" and whether the image is discoverable in the HTML.

Keep the hero or main product image eager and give it priority:

html
<img src="/hero.jpg" alt="Trail running shoes on a rock" width="1600" height="900" fetchpriority="high">

A handful of eager images at the top of the page is normal. The goal is that everything below the first screen is lazy.

Why it happens

  • Older themes and templates written before native lazy loading existed.
  • Hand-written <img> tags in page builders, CMS content and email style landing pages.
  • Image components with loading="eager" everywhere, often set once to fix a slow hero and then copied to every image.
  • JavaScript lazy loaders that broke after an update, leaving every image to load immediately.

How to find images without lazy loading

  1. Check a single page. In Chrome DevTools, open the Network panel, filter by Img and reload without scrolling. Every image that downloads before you scroll is loading eagerly.
  2. Check Lighthouse. Lighthouse 13 removed the separate offscreen images audit. The LCP request discovery insight still shows whether the main image was lazy loaded.
  3. Check what search engines see. In Search Console, URL Inspection shows the rendered HTML. Image URLs should sit in the src attribute, not only in a data-src attribute that a script fills in later.
  4. Check every page. UpCrawler flags Images without lazy loading when a page has more than a few images without loading="lazy". The issue lists examples, so you can see whether the cause is a gallery, a product grid or a template that sets every image to eager. A few eager images at the top of the page, such as the hero, do not trigger it.

How to fix it

Add loading="lazy" to every image below the first screen, and always include width and height so the browser reserves space and the page does not jump when images arrive. Keep the main image at the top eager with fetchpriority="high". Fix it in the image component or template, not image by image. Lazy loading pairs well with removing render-blocking resources, since both free the first screen to paint sooner.

next/image lazy loads by default, so images rendered with it are already handled. For the main image above the fold, load it eagerly with high priority:

tsx
import Image from 'next/image'

<Image
  src="/hero.jpg"
  alt="Trail running shoes on a rock"
  width={1600}
  height={900}
  loading="eager"
  fetchPriority="high"
/>

The preload prop, which replaced the deprecated priority in Next.js 16, adds a preload link in the <head>. Use it only when one image is clearly the LCP element on every viewport, and never together with loading or fetchPriority. For fill and responsive images, pass sizes so the browser downloads the right width. Raw <img> tags in components and markdown content do not get the lazy default, so add loading="lazy" to them yourself.

WordPress core adds loading="lazy" to images in content automatically. Since version 6.3 it keeps the first few content images eager and adds fetchpriority="high" to the image most likely to be the LCP element. Problems usually come from:

  • Theme templates that print images with a hardcoded loading="eager".
  • Page builders and sliders that output their own <img> tags.
  • Optimisation plugins with conflicting lazy load settings. Keep one lazy loading feature active, not two.

The image_tag filter already sets loading="lazy" for images in sections further down the page. Do not lazy load images above the fold. For a hero image, set it explicitly:

liquid
{{ section.settings.image | image_url: width: 1600 | image_tag: loading: 'eager', fetchpriority: 'high' }}

Check custom sections and older snippets that build <img> tags by hand, and add loading="lazy" with width and height to the ones below the first screen.

Fix with AI

Let AI fix it, page by page.

Paste this prompt into AI with your project open. In UpCrawler, every affected page comes with a prompt like this, already filled in with its URL.

Prompt

Add loading="lazy" plus explicit width and height to offscreen images. Keep the LCP image eager with fetchpriority="high" so lazy loading does not slow first paint.

Frequently asked questions

Does lazy loading hurt SEO?

Not with native loading="lazy". Problems only appear with JavaScript loaders that need a scroll or click to load images, because search crawlers do neither.

Should I lazy load the first image on the page?

No. The image visible on the first screen should load eagerly, ideally with fetchpriority="high". Lazy loading it delays your Largest Contentful Paint.

Do I need a JavaScript library for lazy loading?

No. Native loading="lazy" works in every modern browser. A library only adds code to download and can break if the script fails.

Does lazy loading work for iframes?

Yes. loading="lazy" on an <iframe> defers embedded videos and maps the same way, which often saves more than images do.

Found this useful?

Share it with whoever runs your site’s SEO.

Related issues

All SEO issues
Ready when you are!Crawly, the UpCrawler mascot

Catch issues like this on every page.

UpCrawler crawls your whole site, groups affected pages by template and hands you the fix for your platform.

14 days freeNo cardNothing to install