Skip to content
C.W.K.
Stream
Lesson 04 of 08 · published

next/image

~22 min · next/image, optimization, CLS

Level 0Curious
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

What the component buys you

<Image> wraps <img> with: format conversion (WebP/AVIF), responsive sizes, lazy loading, blur-up placeholders, and reserved space (no Cumulative Layout Shift). The optimizer runs at the edge on Vercel; sharp takes over self-hosted.

Local vs remote images

Local images (import) get their dimensions auto-detected. Remote images need explicit width and height so the layout reserves space; the host has to be in images.remotePatterns.

v16: preload, not priority

The above-the-fold hint was renamed from priority to preload. Old code still works but logs a deprecation warning.

Fill mode for unknown sizes

fill stretches to the parent container; pair with object-fit via Tailwind/CSS and a sizes hint for responsive serving.

Give next/image enough information to reserve layout space and choose an efficient resource: dimensions or fill, an accurate sizes expression, and priority only for the actual above-the-fold LCP candidate. Restrict remote sources explicitly.

Automatic optimization cannot infer display geometry or art direction. An incorrect sizes value can download an oversized image, while blanket priority competes for bandwidth. A third-party image host also needs a deliberate trust and cost boundary. Inspect srcset, the selected resource, intrinsic and rendered dimensions, and the network priority at phone and desktop widths. Measure LCP and CLS, test a failed remote image, and confirm an unapproved hostname is rejected.

Code

Local image, auto-sized·tsx
import Image from 'next/image';
import hero from '@/public/hero.jpg';

export function Hero() {
  return (
    <Image
      src={hero}
      alt="Hero"
      placeholder="blur"
      preload  // v16 — replaces 'priority'
    />
  );
}
Remote image with explicit dimensions·tsx
// next.config.ts
import type { NextConfig } from 'next';
const config: NextConfig = {
  images: {
    remotePatterns: [
      { protocol: 'https', hostname: 'images.example.com', pathname: '/**' },
    ],
    formats: ['image/avif', 'image/webp'],
  },
};
export default config;

// In a component:
<Image src={user.avatarUrl} alt={user.name} width={48} height={48} className="rounded-full" />
Fill + object-fit for responsive backgrounds·tsx
<div className="relative h-64 w-full">
  <Image
    src="/background.jpg"
    alt=""
    fill
    sizes="100vw"
    className="object-cover"
  />
</div>

External links

Exercise

Replace every plain <img> in your project with <Image>. For remote images, register the host in remotePatterns. Confirm Lighthouse's CLS score drops to 0.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.