Next.jsReactImage OptimizationPerformance

Next.js Image Guide: sizes, fill, and Remote Images

Use the modern Next.js Image component with width and height, fill, sizes, preload, placeholders, remotePatterns, and clear rules for avoiding outdated layout props.

·Updated ·11 min read·Counting...
Next.js Image Guide: sizes, fill, and Remote Images

The most common Next.js Image mistake is not failing to display an image. It is copying old examples that still use layout="responsive", layout="fill", or component props such as objectFit. Modern Next.js Image usage centers on width, height, fill, sizes, preload, placeholders, and trusted remote image sources.

What Image does for you

next/image extends the native img element with image optimization features. It can help:

  • Serve appropriately sized images for different devices.
  • Reduce layout shift by preserving image dimensions.
  • Lazy-load non-critical images.
  • Support placeholders for important visual areas.
  • Apply a consistent pipeline for local and remote images.

It does not decide which image is your LCP image, what responsive size each layout needs, or which remote sources are safe. Those decisions are still yours.

Fixed-size images

import Image from "next/image"

export default function Avatar() {
  return (
    <Image
      src="/images/avatar.png"
      alt="Author avatar"
      width={160}
      height={160}
    />
  )
}

width and height describe the intrinsic image size. They help the browser reserve the right aspect ratio, but CSS can still control the final rendered size.

When to use fill

Use fill when the image must cover or fit a parent container whose size is controlled by layout CSS:

<div className="relative h-64 w-full">
  <Image
    src="/images/hero.jpg"
    alt="Hero image"
    fill
    sizes="100vw"
    style={{ objectFit: "cover" }}
  />
</div>

Two rules matter:

  • The parent needs positioning, such as position: relative.
  • A fill image normally needs a correct sizes value.

Why sizes matters

Without sizes, the browser may assume an image is close to full viewport width. In a card grid, that can mean downloading a much larger image than needed.

<Image
  fill
  src="/images/card-cover.jpg"
  alt="Article cover"
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
  style={{ objectFit: "cover" }}
/>

sizes should describe the rendered width of the image at different breakpoints. It is not decoration; it is part of the responsive image contract.

Outdated patterns to stop copying

Old tutorials may show:

<Image layout="responsive" objectFit="cover" />

Use modern props instead:

  • Fixed image: width and height
  • Container-filling image: fill
  • Object behavior: CSS class or style
<Image
  fill
  src="/images/banner.jpg"
  alt="Banner"
  style={{ objectFit: "cover", objectPosition: "center" }}
/>

preload, loading, and placeholders

Only the most important above-the-fold image should be considered for preload:

<Image
  src="/images/hero.jpg"
  alt="Product hero"
  width={1440}
  height={720}
  preload
/>

Do not preload every card image in a list. That competes with the browser's normal prioritization and can make performance worse.

For visual areas where a blank load state feels poor, use a placeholder:

<Image
  src="/images/cover.jpg"
  alt="Article cover"
  width={1200}
  height={630}
  placeholder="blur"
  blurDataURL="data:image/jpeg;base64,..."
/>

Remote images and remotePatterns

External image URLs must be allowed in Next.js configuration. Modern projects should use remotePatterns rather than copying old domains examples.

This is a security and operational boundary: you are telling the image optimization pipeline which remote hosts and paths it is allowed to fetch.

If the image requires authentication headers, the default optimizer may not be the right tool. Consider public assets, a controlled proxy, or unoptimized only when you understand the tradeoff.

Real project patterns

Article cover:

<Image
  src={coverImage}
  alt={title}
  width={1200}
  height={630}
  sizes="(max-width: 768px) 100vw, 720px"
  style={{ width: "100%", height: "auto" }}
/>

Card thumbnail:

<div className="relative aspect-[16/9] overflow-hidden rounded-lg">
  <Image
    src={thumbnail}
    alt={title}
    fill
    sizes="(max-width: 768px) 100vw, 33vw"
    style={{ objectFit: "cover" }}
  />
</div>

The first is dimension-led. The second is container-led. Mixing the two mental models is where many bugs start.

Subscribe to FreeMac

Weekly picks: free Mac software reviews, trusted source updates, alternatives, and low-friction guides.