Images account for the largest portion of page weight on most websites. A single unoptimized hero image can tank your Largest Contentful Paint (LCP) score and push your Core Web Vitals into the red. The next/image component exists to solve this problem at the framework level — automatic format negotiation (WebP, AVIF), responsive srcset generation, lazy loading by default, and built-in layout shift prevention.
The component is not just a convenience wrapper around <img>. It is an image optimization pipeline: your original source image goes in, and the browser receives the smallest possible file in the best supported format, sized exactly for the device viewport. You get this with zero manual work beyond choosing the right props.
Master next.js image optimization
Take the Next.js Full-Stack course with hands-on lessons and challenges.
The hero image uses fill to span its parent container, sizes="100vw" because it is full-width, and preload so the browser starts fetching it immediately (this is your LCP element). The static import gives you a free blur placeholder while the full image loads. No width/height needed with fill — the parent's dimensions control the rendered size.
The sizes prop matches the grid layout: 50vw on mobile (2 columns), 33vw on tablet (3 columns), 25vw on desktop (4 columns). This tells the browser exactly how wide the image renders at each breakpoint, so it picks the smallest sufficient variant from the srcset. Without sizes, every product image would download at 100vw — 2x to 4x larger than necessary.
Avatars are a textbook case for fill mode — the container is a fixed circle, and you want the image to cover it regardless of source dimensions. The sizes prop is set to the pixel size of the avatar, so the browser downloads the smallest variant that covers it (no point loading a 1920px image for a 48px circle). The onError fallback shows initials when the remote URL fails.
remotePatterns is your allowlist — only these origins get optimized. Be specific with pathnames (don't leave it open to the entire hostname). The formats array enables AVIF with WebP fallback: AVIF compresses ~20% smaller but encodes slower on first request. Setting qualities to [50, 75] limits the optimization API to only those two levels, preventing abuse on self-hosted deployments.
Art direction means serving a different crop, not just a different size. A wide panoramic shot works on desktop but loses detail on mobile — you want a square crop instead. getImageProps generates the optimized srcset without rendering an Image component, so you can use a standard <picture> element with media queries. Both sources get Next.js optimization (format negotiation, responsive widths).
Omitting the `sizes` prop on responsive images — the browser defaults to assuming the image is 100vw wide and downloads a massive variant
Always set `sizes` to match your CSS layout. If an image sits in a 3-column grid, use `sizes="(max-width: 768px) 100vw, 33vw"`. This is the single highest-impact optimization you can make after using the component at all.
Setting `preload` (or the deprecated `priority`) on every image above the fold — this blocks rendering while all of them race to download
Only one image per page should get `preload`: the one that drives your LCP score. For most pages that is the hero image or the main content image. Everything else should lazy-load or use `loading="eager"` if it is critical but not LCP.
Using `fill` without setting `position: relative` on the parent — the image either overflows or collapses to zero height
The parent must have `position: relative` (or `absolute`/`fixed`) and explicit dimensions. A common pattern is `<div className="relative aspect-video">` to let Tailwind handle both the positioning and the aspect ratio.
Adding remote image hostnames to the old `domains` array instead of `remotePatterns` — this provides no path restriction and is deprecated
Use `remotePatterns` with specific `protocol`, `hostname`, `pathname`, and `search` fields. This limits optimization to exactly the URLs you expect, preventing your image API from being used as a proxy for arbitrary external content.
The `next/image` component handles format negotiation, responsive srcset generation, lazy loading, and layout shift prevention — but only if you use it correctly. The sizes prop is non-negotiable for responsive layouts (without it, every image downloads at viewport width). Use fill mode when the container controls the dimensions, static imports for local assets with free blur placeholders, and preload only for the single LCP image. Configure remotePatterns tightly, enable AVIF for maximum compression, and let the framework do what it was built for.
Interactive lessons and challenges on Stanza, practice in VS Code, Cursor, or the web.
Interactive lessons and challenges, right in your code editor.
Check the free courses. No credit card.