SyntaxStudy
Sign Up
Next.js Optimising Images with next/image
Next.js Beginner 1 min read

Optimising Images with next/image

The next/image component is a drop-in replacement for the HTML img tag that automatically optimises images. It converts images to modern formats like WebP and AVIF, resizes them to the exact dimensions needed for different screen sizes, and serves them via a built-in image optimisation server. Images are lazy-loaded by default, so off-screen images are not fetched until the user scrolls near them. The width and height props are required for local and remote images (unless you use the fill prop). They do not constrain the rendered size — they are used to calculate the aspect ratio and generate appropriate srcset values. You control the rendered size with CSS. The priority prop disables lazy loading for above-the-fold images and adds a link preload tag to the document head, which is critical for your Largest Contentful Paint score. Local images imported from the file system get their width and height automatically detected at build time. Remote images require you to allow the hostname in next.config.js and provide explicit width and height (or use fill). The sizes prop tells the browser the rendered size of the image at different viewport widths, allowing it to download the smallest necessary image from the generated srcset.
Example
// Local image import — width and height inferred automatically
import Image from 'next/image';
import heroImage from '@/public/hero.png';

export default function HeroSection() {
  return (
    <section>
      {/* Local image: width/height from import */}
      <Image
        src={heroImage}
        alt="Hero banner"
        priority           // LCP image — disables lazy load, adds preload
        placeholder="blur" // blurred placeholder while loading
        className="w-full h-auto"
      />
    </section>
  );
}

// Remote image — must allow hostname in next.config.js
function ProductCard({ product }: { product: { name: string; imageUrl: string } }) {
  return (
    <div className="relative">
      {/* fill: image fills the parent container */}
      <div className="relative w-full aspect-square">
        <Image
          src={product.imageUrl}
          alt={product.name}
          fill
          sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
          className="object-cover rounded-lg"
        />
      </div>
      <p>{product.name}</p>
    </div>
  );
}

// Fixed size remote image
function Avatar({ url, name }: { url: string; name: string }) {
  return (
    <Image
      src={url}
      alt={name}
      width={48}
      height={48}
      className="rounded-full"
    />
  );
}