Image Optimization (next/image) in Next.js

The Image component from next/image automatically optimizes images: converts to modern formats, picks the right size for the device and loads lazily.

Why Not a Regular img

A regular <img> loads the original image entirely regardless of screen size. On a mobile device the same 2000px image loads as on desktop. The Image component solves this problem.

Basic Usage

import Image from 'next/image'

export default function ProblemCard() {
  return (
    <Image
      src="/images/problem-preview.png"
      alt="Problem preview on Hack Frontend"
      width={800}
      height={400}
    />
  )
}

What Image Does Under the Hood

1

Format conversion

Automatically converts to WebP or AVIF if the browser supports them. This reduces file size by 30-50%.

2

Device-based resizing

Generates multiple image variants of different sizes. The browser downloads only the appropriate one.

3

Lazy loading

By default images load lazily: only when they enter the viewport. This speeds up initial page load.

4

CLS prevention

Reserves space for the image before it loads, preventing Cumulative Layout Shift.

Local Images

For local files Next.js determines dimensions automatically:

import Image from 'next/image'
import banner from '@/public/images/HackFrontendBanner.png'

export default function Hero() {
  return (
    <Image
      src={banner}
      alt="Hack Frontend"
      placeholder="blur"
    />
  )
}

placeholder="blur" shows a blurred preview before loading. For local images the blur placeholder is generated automatically.

Filling a Container (fill)

When dimensions are not known in advance:

<div className="relative h-64 w-full">
  <Image
    src={user.avatar}
    alt={user.name}
    fill
    className="object-cover rounded-lg"
    sizes="(max-width: 768px) 100vw, 50vw"
  />
</div>

The fill property stretches the image to fill its parent container. sizes hints the browser which variant to download.

The priority Property

For above-the-fold images visible immediately:

<Image
  src="/images/hero.png"
  alt="Hero"
  width={1200}
  height={600}
  priority
/>

priority disables lazy loading and adds a preload hint. Use only for LCP images (1-2 per page).

External Images

For external URLs you need to configure domains in next.config.js:

// next.config.js
module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'avatars.githubusercontent.com'
      },
      {
        protocol: 'https',
        hostname: 'images.unsplash.com'
      }
    ]
  }
}

Security:

Always specify exact domains in remotePatterns. Open access to all domains creates abuse risk through the image optimization API.

Useful Resources