Image Optimization (next/image)
<img> tag leaves every optimization decision to you — the right file format, the right size for the viewport, when to load it, and how to prevent it from shifting the layout as it loads in. The <Image> component from next/image handles all of that automatically.Benefit | What it means in practice |
|---|---|
Responsive sizing | Serves an appropriately sized image for the device, instead of shipping one giant file to every screen |
Lazy loading by default | Images outside the viewport are not fetched until the user scrolls near them |
Automatic format conversion | Serves modern formats like WebP or AVIF to browsers that support them, falling back gracefully otherwise |
Layout-shift prevention | Reserves the correct amount of space before the image loads, avoiding Cumulative Layout Shift |
A basic example
app/page.tsx
import Image from 'next/image'
import profilePic from '../public/profile.png'
export default function Page() {
return (
<Image
src={profilePic}
alt="Author profile picture"
// width and height are set automatically for static imports
/>
)
}width and height automatically. For images loaded from a URL — remote images, or images passed as a string path — you have to supply those dimensions yourself.Remote image — width/height required
import Image from 'next/image'
export default function Avatar() {
return (
<Image
src="https://example.com/avatar.jpg"
alt="User avatar"
width={64}
height={64}
/>
)
}fill prop, width and height are required for any image loaded from a remote URL or passed as a plain string. Next.js needs those dimensions to compute the correct aspect ratio and reserve space for the image before it downloads — without them, the browser has no idea how much room to leave, and the surrounding content jumps around as the image pops in. Use fill instead of fixed dimensions when the image should stretch to fill a parent container of unknown or dynamic size.Using fill inside a sized parent
import Image from 'next/image'
export default function Hero() {
return (
<div style={{ position: 'relative', width: '100%', height: 400 }}>
<Image
src="/hero.jpg"
alt="Hero banner"
fill
style={{ objectFit: 'cover' }}
/>
</div>
)
}Remote images need explicit configuration
images.remotePatterns in next.config.mjs, or the <Image> component will throw at request time.next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'images.example.com',
pathname: '/**',
},
],
},
}
export default nextConfigThe priority prop
priority tells Next.js to preload it and skip lazy loading, so it starts fetching as early as possible.<Image
src="/hero.jpg"
alt="Hero banner"
width={1200}
height={600}
priority
/>priority on at most one or two above-the-fold images per page. Marking every image as a priority defeats the purpose — the browser can only truly prioritize a handful of requests at once.<Image>automatically handles responsive sizing, lazy loading, modern format conversion, and layout-shift prevention.Fixed
width/height(orfillfor a sized parent) are required so Next.js can reserve space before the image loads.Remote image hosts must be allow-listed via
images.remotePatternsinnext.config.mjs.Use the
priorityprop on the page’s LCP image to preload it and skip lazy loading.