Reference guide · images · Published 2026-08-16 · 4 min read
How browsers pick a srcset image
How browsers pick srcset images with w descriptors and sizes: the density math, the first-fit rule, and the mismatch traps that cause big downloads.
- ·The three inputs
- ·The two-step pick
- ·Why it overlaps
The three inputs the browser uses
A browser's srcset picker needs three numbers, and it derives the answer from them:
- The candidate list: every
wdescriptor in thesrcset(e.g.photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w). - The rendered width: the
sizesattribute at the current viewport (e.g.sizes="(min-width: 800px) 50vw, 100vw"). This is the width in CSS pixels that the<img>will occupy in the layout. - The device pixel ratio (DPR): 1 for a normal screen, 2 for most phones, 3 for a high-end phone.
The two-step algorithm
The choice happens in two steps, and the second one surprises people.
Step 1, scale the wanted width by DPR. Compute wantedWidth = renderedWidth * DPR. A 50vw rendered image on a 750px viewport with a 2x phone wants 375 * 2 = 750 effective pixels.
Step 2, pick the smallest candidate whose intrinsic width is at least the wanted width. The browser walks the list from smallest to largest and takes the first descriptor where candidateW >= wantedWidth. Only when none fits does it pick the largest. This is the "minimum viable candidate" rule, not "closest to the target", which surprises most people.
For the classic example:
<img srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
sizes="(min-width: 800px) 50vw, 100vw"
alt="...">
- A 375px-wide phone viewport:
375 * 2 = 750, first candidate >= 750 is800w. The phone downloadsphoto-800.jpg, not the1200w. - The same phone in portrait with
100vw:375 * 3 = 1125, so it picks1200w. High-DPR phones intentionally download big. - A desktop at
50vwof an 1800px viewport:900px, hence1200wonly if the 900px candidate does not exist; with the three files above it picks1200w.
The rule is deliberate: the browser always errs toward the smallest file that cannot look worse than the CSS size, which keeps bytes low and sharpness guaranteed. The sizes attribute article explains why an absent or wrong sizes default to 100vw breaks the whole math.
The DPR twist
The most common mismatch "why is my 400w file not chosen on mobile" comes from ignoring DPR. A 360px-wide phone at DPR 3 computes 360 * 3 = 1080, so it needs a file of 1080w, and your smallest candidate is 400w. The browser walks to 1200w. If you see huge files on phones, check the DPR factor before blaming sizes: the fix is more candidates or a realistic DPR-aware pipeline, not a lower sizes.
The overlap on src and the fallback
When no candidate matches (for example, an old browser that does not parse srcset), the browser uses src with the sizes ignored. Keep src pointing at a good middle file. Also note: the browser prefetches with the network priority order and the intersection of candidates it knows; a LCP image should be the fetchpriority="high" one, covered in the LCP article.
Verify the choice
In DevTools, the Network tab shows the exact URL requested with the ? query timestamp. Compare against your manual math:
- Set the device emulation DPR explicitly.
- Note the rendered width from the layout overlay.
- Compute
wantedWidth = rendered * DPR. - Confirm the smallest candidate >= that number was fetched.
A mismatch almost always means sizes does not match the CSS layout width (a common cause of downloading a 1200px file for a 150px avatar) or the candidate list misses the desired size. The gap between the largest candidate and the rendered size is where the browser quietly picks a candidate you never anticipated, which shows up as an unexpectedly large download in the Network view.
What the DPR skew means for your files
- Include a candidate at or near every real
wantedsize: if your layout renders at 300, 600, 900 and 1200 px and phones want 2-3x, 400/800/1200 covers 1x, 2x, and high-DPR on the 375px phone only partially. Add 1600w and 2000w where LCP matters. - Do not let the largest candidate be the only one a high-DPR phone can pick: a 2000w file downloads fully.
- The size you generate must match the
wdeclared: a file labeled800wthat is really 1000px wide defeats the algorithm and over-fills the cache.
The sibling articles cover the rest of the responsive-image stack: the srcset basics, the sizes attribute, and the optimisation guide for the pipeline that produces the candidates.