Technology · Next.js

Next.js Image Optimization

Optimize images in Next.js using the Image component for better performance.

TL;DR
  1. 01Use next/image instead of img tags for automatic optimization.
  2. 02Lazy loading and responsive resizing happen automatically.
  3. 03Specify width and height to prevent layout shift and improve scores.

Basic Image Component

  • Import and use Image component from next/image.
    import Image from 'next/image';
    
    export default function Hero() {
      return (
        <Image
          src="/hero.jpg"
          alt="Hero image"
          width={1200}
          height={600}
        />
      );
    }
  • Always specify width and height for best performance.
  • alt text is required for accessibility.
  • Images are served as WebP automatically for supported browsers.
  • Use the placeholder prop to show a blur while the image loads.
    import Image from 'next/image';
    import heroImg from '@/public/hero.jpg';
    
    <Image
      src={heroImg}
      alt="Hero"
      placeholder="blur" // works with static imports automatically
    />
  • Use blurDataURL to provide a custom blur placeholder for external images.
    <Image
      src="https://cdn.example.com/photo.jpg"
      alt="Photo"
      width={800}
      height={600}
      placeholder="blur"
      blurDataURL="data:image/png;base64,..."
    />

Local vs External Images

  • Local images in public folder.
    import Image from 'next/image';
    import heroImage from '@/public/hero.jpg';
    
    <Image src={heroImage} alt="Hero" />
  • External images need domain configuration.
    // next.config.js
    module.exports = {
      images: {
        domains: ['cdn.example.com', 'images.example.com']
      }
    };
  • Use remotePatterns instead of domains for more precise allowlisting.
    module.exports = {
      images: {
        remotePatterns: [{ hostname: "cdn.example.com", pathname: "/uploads/**" }]
      }
    };
  • Static imports infer width, height, and enable blur placeholder automatically.
    import logo from '@/public/logo.png'; // width/height inferred
    <Image src={logo} alt="Logo" />
  • Use unoptimized to skip optimization for SVGs or animated GIFs.
    <Image
      src="/icon.svg"
      alt="Icon"
      width={32}
      height={32}
      unoptimized
    />

Responsive Images

  • Use fill prop for responsive sizing.
    <Image
      src="/hero.jpg"
      alt="Hero"
      fill
      style={{ objectFit: 'cover' }}
    />
  • Specify sizes for responsive images.
    <Image
      src="/card.jpg"
      alt="Card"
      width={300}
      height={200}
      sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
    />
  • The fill image must be inside a positioned container.
    <div style={{ position: "relative", width: "100%", height: "400px" }}>
      <Image src="/banner.jpg" alt="Banner" fill style={{ objectFit: "cover" }} />
    </div>
  • Use objectPosition to control the focal point of a filled image.
    <Image
      src="/portrait.jpg"
      alt="Portrait"
      fill
      style={{ objectFit: "cover", objectPosition: "top center" }}
    />
  • Use sizes to help the browser choose the right srcset variant.
    <Image
      src="/hero.jpg"
      alt="Hero"
      fill
      sizes="100vw" // full-width image
    />

Lazy Loading

  • Lazy loading is automatic by default.
    <Image
      src="/below-fold.jpg"
      alt="Below fold image"
      width={800}
      height={600}
      loading="lazy" // Default behavior
    />
  • Disable lazy loading for above-fold images.
    <Image
      src="/hero.jpg"
      alt="Hero"
      width={1200}
      height={600}
      priority // Load immediately
    />
  • Use priority on the largest above-fold image to improve LCP score.
  • Eager loading loads the image immediately without waiting for viewport.
    <Image
      src="/logo.png"
      alt="Logo"
      width={120}
      height={40}
      loading="eager" // Don't defer
    />
  • Images outside the viewport are deferred until the user scrolls near them.
    <Image
      src="/infographic.png"
      alt="Infographic"
      width={800}
      height={600}
      // loading="lazy" is the default — no need to set it explicitly
    />

Image Quality

  • Control image quality with quality prop.
    <Image
      src="/photo.jpg"
      alt="Photo"
      width={500}
      height={300}
      quality={80} // 1-100, default 75
    />
  • Format automatically optimized for browser.
    // Automatically serves WebP to browsers that support it
    <Image
      src="/photo.jpg"
      alt="Photo"
      width={500}
      height={300}
    />
  • Lower quality to 60–70 for hero images that cover large areas.
    <Image src="/hero.jpg" alt="Hero" fill quality={65} />
    // Good visual quality at smaller file sizes for large backgrounds
  • Configure global image quality defaults in next.config.js.
    module.exports = {
      images: {
        qualities: [75, 90], // only generate these quality variants
        minimumCacheTTL: 86400 // cache optimized images for 1 day
      }
    };
  • Use quality={100} for images where accuracy matters like product photos.
    <Image
      src="/product-detail.png"
      alt="Product"
      width={600}
      height={600}
      quality={100}
    />

Tip: Always specify width and height — it prevents layout shift and improves performance significantly.

Warning: Don't use Image for images that change dimensions frequently — use regular img tags instead.

Next.js Getting StartedNext.js Link and Navigation