Performance

srcset and sizes without mistakes

srcset lists the variants, sizes says how much room the image takes. Without sizes the browser fetches the largest file: syntax, mistakes and checks.

Key points

  • With the w descriptor the browser picks the variant from sizes and screen density.
  • Without sizes the browser assumes 100vw and takes the largest file.
  • srcset does not convert formats or create variants: the files must exist.

srcset lists the variants with their width in w, sizes says how much room the image takes in the layout. Without sizes the browser assumes 100vw and fetches the largest file it has.

w, x and sizes: who decides

With the w descriptor the browser multiplies the space declared in sizes by the screen density and picks the variant that covers it. With x it picks by density and ignores the layout. The two descriptors are never mixed in the same srcset.

The mistakes that cost bytes

MistakeWhat the browser fetchesFix
Missing sizesThe largest variant, alwaysDeclare the real width of the container
sizes too wideA variant larger than neededMatch sizes to the layout breakpoint
w and x togetherThe first valid variantUse w with sizes only
Missing width and heightNothing extra, but the layout movesAdd width, height and aspect-ratio

Correct markup

width and height give the aspect ratio even when CSS overrides the sizes. If the image sits above the fold, drop loading="lazy": deferred loading on an LCP element makes the metric worse.

Check the choice, not the syntax

document.querySelectorAll("img").forEach((img) => console.log(img.currentSrc, img.naturalWidth));

In DevTools open Network, filter Img and look at which file actually arrives: if the 980 variant arrives at a 375 px viewport, the problem is sizes. currentSrc is the variant the browser chose, not the one you wrote.

The limitation you have to name

srcset does not convert formats and does not create the variants: the files must exist, at the widths you declare. AVIF or WebP need picture with source elements, and a hand-written srcset ages with the first layout change: in our catalogue the component generates it, which is why there is a single sizes string to check.

Where to continue

In the catalogue: responsive hero banner, reveal images and hero components. The guides: images with next/image and images without dimensions; the sibling article on LCP and the comparison of Next.js and Vite.

Frequently asked questions

What is the difference between srcset and sizes?

srcset lists the available variants with their width or density, sizes tells the browser how much room the image takes. The browser combines both to pick the file.

Can I use srcset without sizes?

Yes, but only with x descriptors. With w descriptors and no sizes the browser assumes the image fills the viewport width and fetches the largest variant.

Do I need width and height with srcset?

Yes, if you want to avoid layout shift. srcset picks the file, width and height reserve the space: without them the content moves when the image arrives.

Does srcset convert images to WebP?

No. srcset picks among files that already exist. Changing format needs picture with several source elements, or a service that converts on request.

How do I check which file was downloaded?

Read currentSrc in the console, or the request column in DevTools with the Img filter. If the chosen file is larger than the space available, the problem is almost always sizes.