Search across all documentation pages
Serve optimized, responsive images with next/image -- automatic format conversion, lazy loading, and size hints.
Quick-reference recipe card -- copy-paste ready.
import Image from "next/image";
// Local image (auto width/height from import)
import heroImage from "@/public/hero.jpg";
<Image src={heroImage} alt="Hero banner" priority />
// Remote image (must specify width and height)
<Image
src="https://cdn.example.com/photo.jpg"
alt="Product photo"
width={800}
height={600}
/>
// Fill container (responsive, no explicit dimensions)
<div className="relative h-64 w-full">
<Image
src="/banner.jpg"
alt="Banner"
fill
className="object-cover"
sizes="100vw"
/>
</div>When to reach for this: Any time you render an image. next/image handles lazy loading, format conversion (WebP/AVIF), responsive sizing, and CLS prevention out of the box.
// app/gallery/page.tsx
import Image from "next/image";
type Photo = {
id: string;
url: string;
alt: string;
width: number;
height: number
// app/components/product-card.tsx
import Image from "next/image";
import Link from "next/link";
type Product = {
slug: string;
name: string;
price: number;
imageUrl:
// next.config.ts -- configure remote image domains
import type { NextConfig } from "next";
const config: NextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "cdn.example.com",
pathname: "/images/**",
},
What this demonstrates:
fill mode for responsive images in a grid layoutsizes prop telling the browser how wide the image will be at different viewport sizespriority for above-the-fold images (disables lazy loading, adds preload hint)next.config.tsaspect-[4/3] and aspect-square containers to prevent CLSnext/image renders an <img> tag with srcset and sizes attributes. The browser selects the best image size based on the viewport and device pixel ratio.priority prop disables lazy loading and adds a <link rel="preload"> for LCP images.fill prop makes the image fill its parent container (the parent must be position: relative, absolute, or fixed). Use this when you do not know the image dimensions at build time.width and height props set the intrinsic aspect ratio to prevent Cumulative Layout Shift (CLS). They do not set the rendered size -- use CSS for that.Responsive image with explicit breakpoints:
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"
className="w-full h-auto"
/>Placeholder blur (local images):
import heroImg from "@/public/hero.jpg";
<Image
src={heroImg}
alt="Hero"
placeholder="blur" // auto-generates blurDataURL for local images
/>Placeholder blur (remote images):
<Image
src="https://cdn.example.com/photo.jpg"
alt="Photo"
width={800}
height={600}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,/9j/4AAQ..." // must provide manually
/>Disabling optimization (SVGs, animated GIFs):
<Image
src="/logo.svg"
alt="Logo"
width={200}
height={50}
unoptimized // serve the original file as-is
/>import Image, { type ImageProps } from "next/image";
// Extending Image props
type AvatarProps = Omit<ImageProps, "alt"> & {
name: string;
};
function Avatar({ name,
Missing sizes prop with fill -- Without sizes, the browser assumes the image is 100vw wide, downloading an unnecessarily large file. Fix: Always provide a sizes prop that matches your CSS layout.
Remote images require remotePatterns -- Using a remote URL without configuring remotePatterns in next.config.ts throws a build error. Fix: Add the hostname (and optionally pathname pattern) to images.remotePatterns.
fill requires a positioned parent -- If the parent element does not have position: relative (or absolute/fixed), the image breaks out of its container. Fix: Add className="relative" to the parent.
priority on too many images -- Marking many images as priority defeats the purpose and slows down the page. Fix: Only use priority on the LCP image (usually 1-2 images above the fold).
Width and height do not control rendered size -- width={800} height={600} sets the intrinsic aspect ratio, not the displayed size. The image may render smaller or larger depending on CSS. Fix: Use CSS classes (className) to control the rendered dimensions.
AVIF encoding is slow -- AVIF produces smaller files but takes longer to generate on the first request. Fix: Accept the cold-start latency, or remove "image/avif" from images.formats if response time is critical.
| Alternative | Use When | Don't Use When |
|---|---|---|
next/image | All images in a Next.js app (the default choice) | You need raw <img> for a specific reason |
Native <img> tag | Simple static images with no optimization needs | You want automatic WebP/AVIF, lazy loading, and srcset |
<picture> element | You need art direction (different crops at different sizes) | Responsive sizing alone is sufficient |
| Cloudinary or Imgix | You need advanced transformations (crop, watermark, face detection) | Built-in Next.js optimization is enough |
| SVG inline | Icons and illustrations that need to be styled with CSS | Photographic content |
srcset and sizes generationfill when you do not know the image dimensions at build time (e.g., user-uploaded images). The image fills its parent container.width and height when dimensions are known. These set the intrinsic aspect ratio, not the rendered size.<link rel="preload"> hint so the browser fetches it immediately.width and height set the intrinsic aspect ratio for CLS prevention, not the rendered size. Use CSS classes (className) to control the actual display dimensions.
The parent element must have position: relative, absolute, or fixed. Add className="relative" to the parent <div>.
Without sizes, the browser assumes the image is 100vw wide and downloads an unnecessarily large file. Provide sizes to match your CSS layout:
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"Add remotePatterns to next.config.ts:
images: {
remotePatterns: [
{ protocol: "https", hostname: "cdn.example.com", pathname: "/images/**" },
],
}For remote images, you must provide blurDataURL manually (a base64-encoded tiny image). Local images get automatic blur generation with placeholder="blur".
import Image, { type ImageProps } from "next/image";
type AvatarProps = Omit<ImageProps, "alt"> & {
name: string;
};
function Avatar({ name, ...
StaticImageData is the type returned when importing a local image file. Use it when a function or prop can accept either a local import or a URL string:
import type { StaticImageData } from "next/image";
function getImage(url?: string): string | StaticImageData {
return url ?? fallbackImage;
}Use unoptimized for images that should not be processed, such as SVGs or animated GIFs. The file is served as-is without format conversion or resizing.
AVIF produces smaller files but encoding is slower on the first request (cold start). If response time is critical, consider removing "image/avif" from images.formats and using WebP only.