Responsive Images with srcset and sizes
Responsive markup lets the browser choose an appropriate resource before layout finishes. The key is to describe the rendered slot honestly; a long candidate list cannot compensate for an inaccurate sizes value.
Two different responsive problems
| Problem | Tool | Decision owner |
|---|---|---|
| Same crop at different resolutions |
srcset with width descriptors and sizes
|
Browser chooses candidate |
| Different crop or composition |
picture with media conditions |
Author defines art direction |
| Format alternatives |
picture with typed sources |
Browser selects supported source |
| Fixed-density icon | Density descriptors where appropriate | Browser accounts for device density |
How browser selection works
With width descriptors, the browser evaluates sizes to estimate the image’s layout slot in CSS pixels, considers device pixel ratio and other conditions, then selects from srcset. It is a selection hint, not a command; browsers may account for cache and network behavior.
If sizes is omitted for a width-descriptor set, the assumed slot can be much wider than the rendered image. That causes an unnecessarily large download even though multiple candidates exist.
A robust markup pattern
<img src="photo-960.jpg" srcset="photo-480.jpg 480w, photo-960.jpg 960w, photo-1440.jpg 1440w" sizes="(max-width: 700px) calc(100vw - 32px), 720px" width="1440" height="960" alt="Ceramic bowl on a workshop table"> The fallback src remains important. Width and height establish an intrinsic aspect ratio and reduce layout movement. Alt text describes the image’s purpose; responsive markup does not change accessibility requirements.
Derive sizes from layout
- Inspect the image’s actual CSS width at each breakpoint.
- Express the first matching media condition and slot width.
- End with the default slot.
- Include container padding and maximum width.
- Retest whenever the layout changes.
For a two-column card that becomes full-width, the slot might be roughly half the container on desktop and viewport width minus padding on mobile. Do not copy a sitewide 100vw value into cards that never occupy the full viewport.
Choose useful candidates
Create enough widths to avoid severe over-download without generating nearly identical files. Candidate spacing can widen as dimensions grow. Base the largest candidate on the maximum rendered slot multiplied by the highest device density you intentionally support; unlimited “retina” exports can waste storage and encoding work without a visible benefit.
Generate every candidate from the master, not from the previous smaller derivative. Keep crops consistent for resolution switching.
Use picture deliberately
<picture> <source type="image/avif" srcset="hero-800.avif 800w, hero-1600.avif 1600w"> <source type="image/webp" srcset="hero-800.webp 800w, hero-1600.webp 1600w"> <img src="hero-1600.jpg" srcset="hero-800.jpg 800w, hero-1600.jpg 1600w" sizes="100vw" width="1600" height="900" alt="...">
</picture> Keep an img fallback with src. Format negotiation is useful only if every source has equivalent content and dimensions. For art direction, use media conditions to provide intentionally different crops and keep the same meaning.
LCP images need different treatment
Do not lazy-load the likely Largest Contentful Paint image. Ensure it is discoverable in initial HTML, receives suitable priority, and has an accurate candidate set. Below-the-fold images can use native lazy loading. The diagnostic guide for image-related LCP covers discovery and timing.
Testing workflow
- Test narrow, medium, and wide viewports.
- Inspect the rendered slot and selected resource in browser tools.
- Repeat at common device pixel ratios.
- Disable cache to observe first-load selection.
- Confirm intrinsic dimensions prevent layout shift.
- Check visual quality at actual size.
- Measure transferred bytes, not only source dimensions.
Common mistakes
- Using width descriptors without
sizes. - Writing
100vwfor a constrained component. - Omitting the fallback
src. - Lazy-loading the LCP image.
- Generating candidates by repeatedly downsizing derivatives.
- Using
picturefor complexity that ordinarysrcsetsolves. - Letting desktop and mobile crops communicate different meaning.
Professional recommendation
Keep image generation tied to design tokens: content widths, breakpoints, supported densities, and format policy. Add an automated check for missing dimensions and oversized selected candidates, but verify real browser behavior because selection depends on layout. For web derivatives, routes such as JPG to WebP or PNG to WebP solve only encoding; responsive dimensions and markup remain separate work.
Frequently asked questions
Does the browser always choose the smallest file?
No. It chooses a candidate using slot size, density, support, and browser policy; encoded byte size is not declared in srcset.
Should every image use picture?
No. Use it for format alternatives or art direction. Resolution switching usually needs only img, srcset, and sizes.
Can responsive images fix a blurry source?
No. They deliver appropriate derivatives but cannot recover missing source detail.
Authoritative references
See the MDN responsive images guide and Google image SEO best practices.
Worked layout method
For a card that is full-width on mobile, half-width on tablets, and one-third of a capped desktop container, calculate each slot from container width, gaps, and padding. Capture actual rendered widths from representative pages, then choose candidates covering those slots at supported device densities. This produces defensible sizes rather than copied guesses.
Image services and cache control
An image CDN can automate transformations, but constrain allowed widths and qualities, normalize cache keys, and ensure correct media types. Avoid arbitrary URLs that create thousands of nearly identical variants.
Art-direction safeguards
Alternative crops must preserve the same informational purpose. If a mobile crop removes the person or product described by surrounding copy, it changes content rather than merely adapting layout.
Component failure cases
- A card declares
100vwinside a four-column grid. - A modal stretches thumbnail candidates.
- Server markup and client CSS use different breakpoints.
- A preload points to JPEG while
pictureselects AVIF. - Width and height attributes declare the wrong aspect ratio.