React  

How to implement lazy loading in React?

Introduction

When building modern React websites or web apps, images play a huge role in design and user experience. However, loading all images at once can slow down your website, especially for users with slower internet connections or mobile devices. That’s where lazy loading images comes in.

Lazy loading means delaying the loading of images until they are actually visible to the user on the screen (in the viewport). Instead of downloading every image immediately, the browser only loads images when they are needed. This improves your app’s performance and makes the page feel faster.

In this article, we’ll explain how to implement lazy loading images in React in simple, beginner-friendly language. We’ll cover how lazy loading works, its benefits, how to use built-in browser features, how to use the Intersection Observer API, popular React libraries, accessibility and SEO tips, and even a small Java backend example for image optimization.

Why Lazy Loading Images is Important

When a web page contains many images — like an e-commerce site, news site, or a photo gallery — the browser tries to download all those images as soon as the page loads. This can make your site feel slow.

Here’s why lazy loading is so useful:

  1. Faster initial load: Only the visible images (usually the top part of the page) load first. This makes the website appear much faster.

  2. Saves bandwidth: Images that are not visible yet don’t get downloaded immediately. This is great for users with limited internet data, especially in countries like India where mobile data is still metered.

  3. Improved SEO and performance metrics: Google’s ranking depends on performance metrics like LCP (Largest Contentful Paint). Lazy loading helps improve these metrics.

  4. Better user experience: The page becomes interactive sooner, giving a smooth browsing experience.

Lazy loading is one of the easiest ways to make your React site faster without changing much of your design or logic.

Native Lazy Loading with the loading Attribute

Modern browsers like Chrome, Firefox, and Edge support a simple attribute called loading for images. By setting loading="lazy", the browser automatically delays loading the image until it’s needed.

Example in React:

export default function NativeLazyImage({ src, alt, width, height }) {
  return (
    <img
      src={src}
      alt={alt}
      width={width}
      height={height}
      loading="lazy"
      style={{ display: 'block', maxWidth: '100%' }}
    />
  );
}

Explanation:

  • The loading="lazy" attribute is built into the browser — no extra library is needed.

  • Always provide width and height (or use CSS aspect-ratio) to prevent layout shifts.

  • Use alt text for SEO and accessibility.

Best practice: Don’t lazy-load above-the-fold (first screen) images. Load those normally so users see them instantly.

Using Intersection Observer in React

For more control, use the Intersection Observer API. It allows you to detect when an image enters the viewport and load it dynamically.

Here’s a React hook for it:

import { useEffect, useRef, useState } from 'react';

export function useLazyImage(options = {}) {
  const imgRef = useRef(null);
  const [isVisible, setIsVisible] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          setIsVisible(true);
          observer.disconnect();
        }
      });
    }, options);

    if (imgRef.current) observer.observe(imgRef.current);

    return () => observer.disconnect();
  }, [options]);

  return [imgRef, isVisible];
}

Then use it in a component:

export default function LazyImage({ src, placeholder, alt }) {
  const [imgRef, isVisible] = useLazyImage({ rootMargin: '100px' });

  return (
    <div ref={imgRef}>
      {isVisible ? (
        <img src={src} alt={alt} style={{ width: '100%', height: 'auto' }} />
      ) : (
        <img src={placeholder} alt="Loading..." style={{ filter: 'blur(10px)', width: '100%' }} />
      )}
    </div>
  );
}

Why use this approach?

  • You control when and how images load.

  • Works even in browsers that don’t fully support native lazy loading.

  • Allows for placeholders and smooth transitions.

Using React Lazy Loading Libraries

If you prefer not to write custom code, there are React libraries that make lazy loading even easier:

1. react-lazy-load-image-component

This is one of the most popular libraries for lazy loading images in React.

Example:

import { LazyLoadImage } from 'react-lazy-load-image-component';
import 'react-lazy-load-image-component/src/effects/blur.css';

export default function GalleryItem({ src, alt }) {
  return (
    <LazyLoadImage
      alt={alt}
      src={src}
      effect="blur"
      placeholderSrc="/images/placeholder-small.jpg"
    />
  );
}

Advantages:

  • Adds blur effect automatically.

  • Easy to integrate.

  • Works with SSR (Server-Side Rendering) setups like Next.js.

2. Next.js Image Component

If you’re using Next.js, its built-in <Image /> component automatically handles lazy loading and responsive sizes.

Responsive Images with srcset and sizes

Serving images with the right size improves both performance and appearance. Instead of loading one large image for all screens, let the browser choose the best version.

Example:

<img
  src="/images/photo-800.jpg"
  srcSet="/images/photo-400.jpg 400w, /images/photo-800.jpg 800w, /images/photo-1200.jpg 1200w"
  sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"
  loading="lazy"
  alt="Example image"
/>

Tip: Combine srcset and lazy loading to optimize for every device and connection type.

Using Blurred Placeholders (Progressive Loading)

The blur-up technique improves user experience. A tiny blurred version of the image loads first, followed by the clear version.

Steps:

  1. Generate a small (low-resolution) image.

  2. Show it as a placeholder.

  3. Replace it with the real image once it’s visible.

This makes your app feel faster and smoother.

Accessibility and SEO Considerations

  1. Always include alt text – It helps users who use screen readers and improves SEO.

  2. Server-Side Rendering (SSR) – Ensures images are visible to Google bots.

  3. Avoid lazy loading above-the-fold images – Google’s LCP metric depends on these.

If you’re targeting users or developers in regions like India, ensuring fast load times on mobile is crucial — and lazy loading helps achieve that.

Java Backend Example for Optimized Images

If your backend is written in Java (Spring Boot), you can dynamically resize images before sending them to the browser.

@GetMapping("/resize-image")
public ResponseEntity<ByteArrayResource> resizeImage(@RequestParam String path, @RequestParam int width) throws Exception {
    BufferedImage original = ImageIO.read(new File(path));
    int height = (original.getHeight() * width) / original.getWidth();

    Image tmp = original.getScaledInstance(width, height, Image.SCALE_SMOOTH);
    BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2d = resized.createGraphics();
    g2d.drawImage(tmp, 0, 0, null);
    g2d.dispose();

    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ImageIO.write(resized, "jpg", baos);

    ByteArrayResource resource = new ByteArrayResource(baos.toByteArray());

    return ResponseEntity.ok()
            .contentType(MediaType.IMAGE_JPEG)
            .body(resource);
}

This code dynamically resizes the image to the correct width before sending it, saving bandwidth and improving loading time.

Summary

Lazy loading images in React is one of the simplest and most effective ways to make your website faster and more user-friendly. It improves page speed, reduces unnecessary data usage, and enhances SEO. You can use built-in browser lazy loading, Intersection Observer API, or third-party libraries for smooth implementation. Combine lazy loading with responsive images (srcset), blurred placeholders, and backend image optimization for best results. Whether you’re building a blog, an e-commerce site, or a portfolio, lazy loading images in React ensures your app performs well — even on slower connections.