CSS

Getting responsive images right with srcset and sizes

CSS

Several people on our team kept asking for a clear explanation of `srcset` and `sizes` beyond "it makes images responsive," so here is the explanation we now give, written down properly for the first time rather than repeated slightly differently in conversation every time someone new asks.

`srcset` lists multiple versions of an image at different resolutions, each with a width descriptor. `sizes` tells the browser how wide the image will actually be displayed at different viewport widths — it is not about the image's real dimensions, it is a hint about layout. The browser combines both pieces of information with its knowledge of the device's pixel density to decide which image file to actually download, before it even starts rendering the page, which is the part people tend to find least intuitive: the browser is making this decision on its own, based on information you provide, rather than you telling it directly which file to load.

Where this actually goes wrong in practice

Getting `sizes` wrong is the most common mistake we see — it needs to match your actual CSS layout, not just be a rough guess, or the browser will pick images that are needlessly large or noticeably blurry. A common version of this mistake: a developer sets `sizes="100vw"` as a safe-seeming default without checking that the image genuinely renders at full viewport width at every breakpoint, when in practice a two-column layout on tablet means the image is actually rendered at closer to half that width, and the browser — trusting the inaccurate hint it was given — downloads an unnecessarily large file for no visual benefit whatsoever.

The concrete result of fixing it properly

On a recent client site, correcting a wrong `sizes` value across the site's product images cut average page weight by nearly a third with zero visible difference to users, which is the kind of result that makes a strong case for treating `sizes` as something worth getting right deliberately rather than filling in with a plausible-looking default and moving on. We now include a specific `sizes`-accuracy check as part of our standard pre-launch performance review, checked against the actual rendered layout at each breakpoint rather than assumed from the design comp alone.

Art direction with the picture element, a related but different problem

`srcset` and `sizes` solve resolution switching — showing the same image, cropped the same way, at an appropriately sized file for the viewport. A separate problem, art direction, is showing a genuinely different crop or composition at different viewport widths, such as a wide establishing shot on desktop swapping to a tighter portrait crop on mobile, which needs the `<picture>` element and its `<source>` children with `media` conditions instead. We have started explaining these as two related but distinct tools to the same designers and junior developers who originally asked about `srcset`, since conflating the two leads to reaching for the wrong one and being confused about why it does not behave as expected.

How this interacts with lazy loading

Lazy-loading an image below the fold and getting its `srcset` sizing right are two separate concerns that still need to cooperate correctly, since a lazy-loaded image needs accurate layout dimensions reserved for it before it loads, or the page shifts visibly once it finally appears — a problem independent of `srcset` itself but one that shows up more often on image-heavy pages using both techniques together. We now require an explicit `width` and `height` attribute (or an equivalent aspect-ratio box) on every responsive image specifically to prevent this layout shift, treating it as part of the same pre-launch performance review that already checks `sizes` accuracy.

← Back to the journal

Have a project in mind?
Let’s talk.

Tell us where you are and where you want to go. We'll map the fastest route between the two.

Currently accepting new clients