On an HTML <img>, what do the srcset and sizes attributes do, and what is the difference between a w descriptor and an x descriptor inside srcset?
answer
- one image, several encodings
- descriptor describes the file
- display width must be declared too
- fixed box wants density, not width
basics
~20 ssrcset lists interchangeable files for one image: a w descriptor states a file's intrinsic pixel width, an x descriptor targets a device pixel ratio. sizes declares how wide the image will render, which the browser needs to choose among w candidates.
solid answer
~50 s`srcset` on `<img>` gives the browser a menu of the *same* picture at different resolutions, and the browser picks one. Each candidate carries a descriptor. A **w descriptor** (`hero-800.jpg 800w`) states the file's real pixel width, and it only becomes useful when you also give `sizes` — a CSS length telling the browser how wide the image will actually be laid out, optionally with media conditions like `sizes="(min-width: 900px) 45vw, 100vw"`. From those two the browser works out how many pixels it needs and picks a candidate. An **x descriptor** (`[email protected] 2x`) targets device pixel ratio directly and is right when the rendered size is fixed — a logo or an avatar — because then `sizes` is irrelevant and is ignored. `src` stays as the fallback for anything that does not understand `srcset`. Same image content in every candidate: switching art or crop is `<picture>`'s job, not `srcset`'s.
code
html · 5 lines<img src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
sizes="(min-width: 900px) 45vw, 100vw"
width="1600" height="900"
alt="Harbour at dawn">go deeper
Be ready to write a correct <img> with srcset and sizes from memory and to say plainly that a w descriptor is the file's own pixel width, not a breakpoint.
Explain when x descriptors are the better tool, what the default sizes value is, and why every candidate has to be the same picture rather than a different crop.
Show you can pick a candidate ladder that is worth building and serving, and explain what role src still plays once srcset is present.
Own the tradeoff between generating many derivatives per image and the build, storage and cache cost of doing so, and where that decision lives in a design system.
## The problem responsive images solve A single `src` forces one file on every visitor. A 2000-pixel-wide photograph is right for a wide desktop on a high-density screen and badly wrong for a phone that will paint it 360 CSS pixels across: the phone downloads and decodes several times the bytes it can display. Serving the small file to everyone fixes the phone and leaves the desktop blurry. `srcset` exists so the author can publish several encodings of the *same* image and let the browser choose. ## The srcset syntax `srcset` is a comma-separated list of *image candidate strings*. Each is a URL plus an optional descriptor: ```html <img src="photo-800.jpg" srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w" sizes="(min-width: 900px) 45vw, 100vw" alt="…"> ``` Every candidate must be the same picture — same subject, same crop, same aspect ratio — just encoded at different sizes. Choosing a *different* crop per breakpoint is art direction and belongs to `<picture>` with `<source media>`, not here. ## w descriptors: the file's intrinsic width `photo-800.jpg 800w` says: this file is 800 image pixels wide. It is a statement about the file, not about the viewport and not about a breakpoint. This is the single most common misreading — people write `800w` believing it means "use this below 800px of viewport". It does not; the browser derives that decision itself. To derive it, the browser needs one more fact: how wide the image will be *displayed*. That is what `sizes` supplies. ## sizes: the display width, in CSS pixels `sizes` is a comma-separated list of `<media-condition> <length>` pairs, with a final bare length as the fallback. The browser evaluates the conditions in order and uses the length from the **first** match: ```html sizes="(min-width: 1200px) 600px, (min-width: 640px) 50vw, 100vw" ``` Lengths may be `px`, `em`, `rem`, `vw`, or `calc()` — but **not percentages**, because a percentage would need a containing block the browser has not laid out yet. If `sizes` is omitted while w descriptors are present, the browser assumes `100vw`, which is why full-bleed images accidentally look fine and constrained ones silently over-download. ## x descriptors: density switching When an image's rendered size is fixed by design — an avatar always 48 CSS pixels, a logo always 120 — you do not need the whole `sizes` machinery. You need one file per screen density: ```html <img src="avatar.png" srcset="avatar.png 1x, [email protected] 2x, [email protected] 3x" width="48" height="48" alt=""> ``` With x descriptors, `sizes` has no effect and is ignored. A candidate with no descriptor at all is treated as `1x`. Do not mix the two descriptor kinds in one `srcset`; the HTML standard treats a list that combines width and pixel-density descriptors as an error, so the safe rule is one descriptor type per attribute. ## What src is for once srcset exists `src` remains the fallback for anything that does not implement `srcset`. Beyond that its role depends on the descriptors: when every candidate is an x descriptor and none is `1x`, `src` participates as the `1x` candidate; when any candidate carries a w descriptor, `src` takes no part in the selection and is purely the fallback. Keep pointing it at a sensible mid-size file rather than the largest one. ## Which one should you reach for Ask whether the image's layout width varies with the viewport. - **It varies** (hero, article figure, card in a fluid grid) → w descriptors plus an honest `sizes`. - **It is fixed** (icon, logo, fixed-size avatar) → x descriptors, plus `width`/`height` attributes so the box is known. ## The mistakes that ship - Reading `800w` as a breakpoint and building a fake media-query ladder out of it. - Omitting `sizes` on a constrained image and inheriting the `100vw` default. - Putting a different crop in each candidate — the browser may swap between them at any moment, so the composition changes unpredictably. - Offering candidates that barely differ (`900w`, `950w`, `1000w`): more files to build and cache for no visible gain. - Forgetting `alt`; the responsive plumbing does nothing for accessibility.
- If srcset lets the browser choose, why would you ever still use x descriptors?Because when the rendered box is fixed by design — a 48px avatar, a 120px logo — there is nothing for the browser to compute. `sizes` would just restate a constant, and x descriptors say the only thing that varies: screen density. They are shorter, they cannot go stale when the CSS changes, and they express the intent directly.
- Can you put different crops of the picture in the same srcset to get a tighter mobile composition?No. Every candidate in one `srcset` must be the same image content; the browser may switch between them at will, including after load, so a differing crop would change the composition unpredictably. Art direction — a different crop or a different subject per breakpoint — is what `<picture>` with `<source media>` is for.
- What happens to a browser that does not support srcset at all?It ignores `srcset` and `sizes` as unknown attributes and loads `src`, which is why `src` should point at a sensible middle-sized file rather than the largest candidate. Support is effectively universal in current browsers, so `src` is a safety net rather than a real strategy.
srcset is a menu of the same dish in different portion sizes; sizes is you telling the waiter how big the plate is. Without the plate size, the kitchen guesses the largest one.
saying these in an interview costs you the question
- Thinks 800w means "use below an 800px viewport"
- Puts different crops or subjects in one srcset
- Mixes w and x descriptors in the same srcset
- Omits sizes and assumes the browser measures the element
- Points src at the largest file as the fallback