Recommended Image Dimensions
These are safe starting points, not hard rules — always check what a placement actually renders at before exporting an image larger than it needs to be.
| Image type | Recommended size | Aspect ratio | Format |
|---|---|---|---|
| Hero banner | 1920 × 1080 (desktop), 1200 × 800 (min) | 16:9 or 3:2 | WebP / AVIF |
| Blog featured image | 1200 × 630 | 1.91:1 | WebP |
| Portfolio image | 1600 × 1200 | 4:3 | WebP / AVIF |
| Product image | 1000 × 1000 | 1:1 | WebP / AVIF, PNG for transparency |
| Open Graph image | 1200 × 630 | 1.91:1 | JPEG / PNG |
| Logo (wordmark) | ≈400 × 120 (2x for retina) | varies | SVG |
| Icon / favicon | 32 × 32, 180 × 180 (apple-touch) | 1:1 | PNG / ICO / SVG |
Choosing the Right Image Format
- WebP: The safe default for photos and complex images. 25–35% smaller than JPEG at equivalent visual quality, with wide browser support.
- AVIF: Compresses 20–30% smaller than WebP, but takes longer to encode. Good for hero images and OG images where file size matters most.
- PNG: Reserve for images that need true transparency or crisp flat colors and text (screenshots, UI mockups). Avoid for photos — file sizes balloon quickly.
- JPEG:Still fine as a fallback format, or when a tool in your pipeline doesn't support WebP/AVIF yet.
- SVG: Always for logos, icons, and illustrations made of shapes — infinitely scalable and usually smaller than any raster equivalent.
Responsive Images: srcset and sizes
A single image file can't be the right size for every viewport. The browser needs two pieces of information to pick the best one from a set of candidates:
- srcset — a list of image URLs, each paired with its actual width, e.g.
image-640.jpg 640w, image-1080.jpg 1080w. - sizes — tells the browser how wide the image will actually be rendered at each breakpoint, e.g.
(max-width: 768px) 100vw, 50vw.
Without sizes, the browser assumes the image is as wide as the viewport and downloads a larger file than it needs on smaller screens.
Aspect Ratio and Compression
Set an explicit aspect ratio (via width/height attributes or CSS aspect-ratio) on every image so the browser can reserve the correct space before the file downloads — this is what prevents layout shift.
For compression, a quality setting of 75–85% is usually visually lossless for photos while cutting file size significantly compared to 100%. Push lower (50–65%) for large background or hero images where the human eye is less sensitive to fine detail.
Lazy Loading Images
Lazy loading defers offscreen images until the user scrolls near them, which reduces initial page weight and speeds up everything above the fold. It should be the default for anything below the first viewport.
When Not to Lazy-Load Above-the-Fold Images
Never lazy-load the image that's visible on first load — especially if it's your Largest Contentful Paint (LCP) candidate, like a hero image. Lazy loading it delays discovery and directly hurts LCP. Load it eagerly and, in Next.js, mark it as high priority so the browser fetches it as early as possible.
Using next/image Correctly
next/image handles resizing, format negotiation (WebP/AVIF), and lazy loading for you — but only if the props are set correctly.
Setting sizes
<Image
src="/blog/cover.jpg"
alt="Blog post cover"
width={1200}
height={630}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 800px"
/>Set sizeswhenever the image isn't rendered at a fixed pixel size — without it, Next.js only generates a small 1x/2x srcset instead of the full responsive set.
preload for LCP Images
Starting with Next.js 16, the priority prop is deprecated in favor of preload. Use it on the one image most likely to be your LCP element — typically a hero image above the fold:
<Image
src={heroImage}
alt="Product dashboard preview"
preload
sizes="100vw"
style={{ width: "100%", height: "auto" }}
/>Only use preload on one or two images per page — marking everything as high priority defeats the purpose and competes with the actual LCP image for bandwidth.
Width, Height, and Remote Images
Statically imported images get their width and height automatically. Remote or dynamic images need both set explicitly so Next.js can reserve the right space and avoid layout shift:
// next.config.ts
export default {
images: {
remotePatterns: [
{ protocol: "https", hostname: "cdn.example.com", pathname: "/media/**" },
],
},
};
// component
<Image
src="https://cdn.example.com/media/team-photo.jpg"
alt="Team photo"
width={1600}
height={1200}
/>Remote images must come from a hostname listed in images.remotePatterns in your Next.js config, or the Image Optimization API will reject the request.
Quality Settings
<Image src="/portfolio/case-study.jpg" alt="Case study screenshot" width={1600} height={1000} quality={80} />Since Next.js 16, allowed quality values must be listed in images.qualities in your config (it defaults to [75]) — add any other values you use, like [50, 75, 90], or requests for unlisted qualities will fall back to the closest allowed value.
How Images Affect LCP and CLS
Images are the most common cause of poor Core Web Vitals scores:
- LCP (Largest Contentful Paint):On most pages, the LCP element is an image. An unoptimized, unpriortized, or oversized hero image is the single most common reason LCP exceeds the 2.5s "good" threshold.
- CLS (Cumulative Layout Shift): Images without explicit dimensions load with zero reserved space, then shove content down once they arrive — this is the most common cause of layout shift on the web.
Fixing both usually comes down to the same three things: compress and right-size every image, always set width/height (or use fill inside a sized container), and make sure only the actual LCP candidate is loaded eagerly.
Need help improving your website performance?
We audit Core Web Vitals, image pipelines, and rendering strategy as part of every engagement.
Talk to us