Import Image from next/image and give it src, alt, and either width and height or fill. Add a sizes string whenever the rendered width changes with the screen, so the browser downloads a smaller file. For the hero image that is your LCP, set preload (it replaced priority in Next.js 16). Allow external hosts with images.remotePatterns.
| Prop | Default | Use it when |
|---|---|---|
| width / height | none | The image has a fixed size, or you want the aspect ratio reserved |
| fill | false | The parent box decides the size (cards, heroes, covers) |
| sizes | browser assumes 100vw | The image is responsive or uses fill |
| preload | false | The image is the above-the-fold LCP element |
| loading | lazy | Set eager only for images that must load straight away |
| quality | 75 | Only values listed in images.qualities are served |
Updated
Two image mistakes are easy to make in Next.js: a fill image with no sizes, so phones download desktop files, and a hero that waits for lazy loading. This page explains each prop in plain words, gives you a calculator that writes the sizes string for your layout, and lists the config defaults Next.js uses today.
Choose a layout and breakpoints to generate the sizes attribute, then see which default srcset width a given screen is likely to download.
Default candidate widths: 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840. Browsers may choose differently, for example when a larger file is already cached.
| Prop | Type | What it does |
|---|---|---|
| src | string or static import | Local path in public, imported file, or an external URL allowed by remotePatterns |
| alt | string | Required text alternative; use an empty string only for decorative images |
| width, height | integer (px) | Intrinsic size used for the aspect ratio; not needed for static imports or fill |
| fill | boolean | Stretch to the positioned parent instead of using width and height |
| sizes | string | Media conditions and slot widths that drive srcset selection |
| quality | integer 1 to 100 | Output quality, default 75, snapped to the images.qualities list |
| preload | boolean | Adds a preload link in the head for the LCP image |
| loading | lazy or eager | Defaults to lazy |
| placeholder | empty, blur or data URL | What shows while loading; blur needs blurDataURL unless the image is a static import |
| unoptimized | boolean | Serve the source file as is, without resizing or format changes |
| priority | boolean | Deprecated in Next.js 16; use preload instead |
| Setting | Default | Notes |
|---|---|---|
| deviceSizes | 640, 750, 828, 1080, 1200, 1920, 2048, 3840 | Widths for full-width and fill images |
| imageSizes | 32, 48, 64, 96, 128, 256, 384 | Extra small widths, only used when the image has a sizes prop |
| qualities | 75 | Required allowlist from Next.js 16 |
| minimumCacheTTL | 14400 (4 hours) | The larger of this and the upstream Cache-Control wins |
| remotePatterns | none | Each external host must be listed |
The import gives Next.js the real dimensions and a blur placeholder. preload starts the download from the head.
import Image from "next/image";
import hero from "./hero.jpg";
export default function Hero() {
return (
<Image
src={hero}
alt="Bakery counter with fresh loaves"
placeholder="blur"
preload
sizes="100vw"
style={{ width: "100%", height: "auto" }}
/>
);
}Each card is a third of the page on desktop, half on tablets and full width on phones, and the sizes value says exactly that.
<div style={{ position: "relative", aspectRatio: "4 / 3" }}>
<Image
src={product.photoUrl}
alt={product.name}
fill
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
style={{ objectFit: "cover" }}
/>
</div>Only HTTPS files under /uploads/ on one host are allowed. Two quality values are permitted.
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
images: {
remotePatterns: [
{ protocol: "https", hostname: "cdn.example.com", pathname: "/uploads/**" },
],
qualities: [60, 75],
formats: ["image/avif", "image/webp"],
},
};
export default nextConfig;
A plain img tag sends one file to every device. next/image resizes the source on request, converts it to a modern format the browser accepts, lazy loads it by default and reserves the space so the layout does not jump while it arrives.
The catch is that it can only pick a sensible file when it knows how wide the image will be. That is the job of width, height and sizes, and it is where most real-world mistakes happen.
Largest Contentful Paint is often a hero photo. Lazy loading that photo delays the metric, so mark it with preload, or with loading="eager" plus fetchPriority="high", and leave every image below the fold on the lazy default.
Pair that with an honest sizes value. A hero that spans the full width on phones but only half the page on desktop should say so, otherwise large screens and small screens both get the wrong file.
remotePatterns lists the outside hosts you trust. qualities is an allowlist of quality values and is required from Next.js 16, and the docs default it to 75. formats lets you add AVIF ahead of WebP, at the cost of storing both versions in the cache.
deviceSizes and imageSizes together make up the candidate widths in every srcset. You rarely need to change them, but knowing the defaults helps you read what the browser downloaded in the network panel.
Yes. From Next.js 16 the docs mark priority as deprecated in favour of preload, which inserts a preload link in the head. The docs also say that in most cases loading="eager" or fetchPriority="high" is the better choice, and preload should not be combined with either of those props.
External images must match an entry in images.remotePatterns in next.config. Add an object with protocol, hostname and a pathname such as /photos/**, then restart the dev server. Requests that match no pattern get a 400 response from the image optimizer.
It tells the browser how wide the image will be at each breakpoint before CSS loads. With sizes, Next.js also emits a full width-based srcset (640w, 750w and so on) instead of only 1x and 2x, so a phone can pick a far smaller file.
No. fill and width/height are alternatives. With fill the image stretches to its positioned parent, and you control cropping with object-fit through the style or className prop.
The default minimumCacheTTL is 14400 seconds, which is four hours. The real max age is whichever is larger: that value or the Cache-Control header sent by the original image. Statically imported images get long-lived immutable caching because their file names are hashed.
Related: Website image sizes guide, Optimize images for the web, HTML images, srcset and sizes, Image compressor, Next.js proxy (middleware) examples.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.