picture and srcset
Responsive images in HTML — srcset width descriptors, sizes, art direction with picture/source, and type-based format negotiation.
- html
- picture
- srcset
srcset + sizes let the browser pick a file density/width. <picture> adds art direction and format negotiation. CSS alone cannot choose a smaller download for a smaller layout slot — that’s HTML’s job.
Docs: MDN responsive images, <picture>, srcset.
Width-descriptor srcset
<img
src="/hero-800.jpg"
srcset="
/hero-400.jpg 400w,
/hero-800.jpg 800w,
/hero-1200.jpg 1200w
"
sizes="(min-width: 48rem) 50vw, 100vw"
width="1200"
height="675"
alt="Team workshop at a whiteboard"
loading="lazy"
decoding="async"
/>
wdescriptors — intrinsic width of each filesizes— the image’s display width in CSS pixels under conditions- Browser picks a candidate using viewport, DPR, and sizes
If sizes lies, users get blurry or oversized downloads.
Density descriptors (simpler assets)
<img
src="/icon.png"
srcset="/icon.png 1x, /icon@2x.png 2x"
width="32"
height="32"
alt=""
/>
Good for fixed-size icons; less flexible for fluid layouts than w + sizes.
Art direction with picture
<picture>
<source
media="(max-width: 40rem)"
srcset="/hero-mobile.jpg 800w"
sizes="100vw"
/>
<source
media="(min-width: 40.01rem)"
srcset="/hero-desktop.jpg 1600w"
sizes="100vw"
/>
<img
src="/hero-desktop.jpg"
width="1600"
height="900"
alt="Conference keynote stage"
/>
</picture>
Different crops, not just resolutions — CSS object-fit can’t invent a mobile-specific composition.
Format negotiation
<picture>
<source type="image/avif" srcset="/photo.avif" />
<source type="image/webp" srcset="/photo.webp" />
<img src="/photo.jpg" alt="Product on a desk" width="800" height="600" />
</picture>
First supported type wins; final <img> is required fallback and holds alt/size.
Always keep the img
<picture> without <img> is invalid for providing the image resource. Alt, dimensions, and lazy loading live on the img.
Pair with CSS
img {
max-width: 100%;
height: auto;
}
Layout width must match the story you told in sizes.
Interview out-loud
“srcset with w and sizes lets the browser pick a resolution for fluid images. picture handles art direction via media and formats via type. The nested img is mandatory for alt and fallback. Honest sizes matching CSS layout is the usual bug.”
Footguns
- Only shipping 2x images and calling it responsive.
sizes="100vw"when the image is a 200px thumbnail.- Forgetting width/height → CLS.
- Using picture for format only when a single
<img srcset>with type isn’t available — picture is correct for type switching. - Lazy-loading LCP hero images — often should be eager + high fetch priority.
Debugging wrong candidate
- Network panel → img request → which file downloaded?
- Compare to computed layout width × DPR.
- Fix
sizesfirst, assets second. - Confirm server returns correct Content-Type and dimensions.
<!-- Thumbnail in a 3-column grid -->
<img
src="/t-400.jpg"
srcset="/t-200.jpg 200w, /t-400.jpg 400w, /t-800.jpg 800w"
sizes="(min-width: 64rem) 20vw, (min-width: 40rem) 33vw, 100vw"
width="800"
height="800"
alt=""
loading="lazy"
/>
Tune sizes whenever the grid breakpoints change.
CMS and CDNs
Image CDNs (imgix, Cloudinary, etc.) can generate width variants on the fly. Still emit correct srcset/sizes in HTML — the CDN does not know your layout. Prefer a small set of widths (e.g. 400/800/1200/1600) over infinite variants to keep caches hot. Avoid shipping both art-direction crops and unused full-frame assets on every page.
Hero with format + width
<picture>
<source
type="image/avif"
srcset="/h-800.avif 800w, /h-1200.avif 1200w"
sizes="100vw"
/>
<source
type="image/webp"
srcset="/h-800.webp 800w, /h-1200.webp 1200w"
sizes="100vw"
/>
<img
src="/h-1200.jpg"
srcset="/h-800.jpg 800w, /h-1200.jpg 1200w"
sizes="100vw"
width="1200"
height="675"
alt="…"
fetchpriority="high"
/>
</picture>
Combine type negotiation with width selection carefully — each source can carry its own srcset. Keep descriptors consistent across formats.
Related
- Responsive images CSS
- Images alt and decorative
- object-fit and aspect-ratio
- Preload prefetch in HTML
Further reading
Related guides
- Accessibility Tree OverviewHow browsers build the accessibility tree from DOM and CSS — roles, names, states, what’s pruned, and how to inspect it in DevTools.
- Audio and Video ElementsNative audio/video — controls, sources, captions, autoplay policies, and accessibility requirements for media on the web.
- Autocomplete and Name Attributesname and autocomplete on form fields — password managers, autofill tokens, and why missing names break real users more than demos.
- Base Element and Relative URLsHow <base href> rewrites relative URLs for links, scripts, and forms — powerful for static hosts, dangerous when set accidentally.
- contenteditable Basicscontenteditable surfaces — what the browser gives you, sanitization, keyboard and a11y gaps, and when to pick a real editor library.