Use srcset and sizes to serve responsive WebP at the right resolution per device, with a JPEG fallback. Width and density descriptors explained.
srcset and WebP: Responsive Images Done Right
The srcset attribute serves WebP at the right resolution for each device, while the <picture> element supplies the format fallback. Together they deliver a correctly sized WebP to capable browsers and a JPEG to the rest. This guide covers width and density descriptors, the sizes attribute, and how resolution selection differs from format selection.
For the format-fallback mechanics, see How to Serve WebP Images in HTML Using the picture Element. For the format itself, see What is WebP?.
What is the difference between srcset and picture?
srcset selects the resolution; <picture> with type selects the format. srcset gives the browser several sizes of the same image and lets it choose based on viewport and pixel density. The <picture> element's type attribute chooses WebP, AVIF, or the fallback. They solve different problems and are used together.
Resolution switching with srcset reduces bytes on small screens. Format selection with <picture> reduces bytes on every screen by using WebP.
How do you write a srcset with width descriptors?
List each image source with a width descriptor — the image's intrinsic pixel width followed by w. The browser combines this with the sizes attribute to pick the smallest source that still fills the displayed size. Width descriptors suit images that change displayed size across breakpoints.
<img
src="/img/photo-1200.webp"
srcset="/img/photo-400.webp 400w,
/img/photo-800.webp 800w,
/img/photo-1200.webp 1200w,
/img/photo-1600.webp 1600w"
sizes="(max-width: 768px) 100vw, 1200px"
alt="Description"
width="1200"
height="675"
/>
The number after each file is the file's real width, not a breakpoint. The browser does the matching.
What does the sizes attribute do?
The sizes attribute tells the browser how wide the image will display before layout is computed, so it can pick the right srcset source early. It is a list of media conditions and widths. Without sizes, the browser assumes the image fills the full viewport width.
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 600px"
This reads: below 768px the image spans the full viewport; below 1200px it spans half; otherwise it is 600px wide. Accurate sizes values prevent the browser over-fetching large sources.
When should you use density descriptors instead?
Use density descriptors (1x, 2x) for images that display at a single fixed size regardless of viewport — logos, icons, and avatars. Density descriptors serve a higher-resolution file to high-DPI screens without the complexity of sizes.
<img
src="/img/logo.webp"
srcset="/img/logo.webp 1x, /img/logo@2x.webp 2x"
alt="Company name"
width="200"
height="60"
/>
Use width descriptors with sizes for fluid images; use density descriptors for fixed-size images.
How do you combine srcset with the WebP format fallback?
Put the responsive srcset on a WebP <source> and repeat it on the <img> fallback. The browser selects the WebP source by type, then applies srcset and sizes to pick the resolution. Browsers without WebP fall through to the <img>, which carries its own responsive srcset.
<picture>
<source
type="image/webp"
srcset="/img/photo-800.webp 800w, /img/photo-1600.webp 1600w"
sizes="(max-width: 768px) 100vw, 1200px"
/>
<img
src="/img/photo-1600.jpg"
srcset="/img/photo-800.jpg 800w, /img/photo-1600.jpg 1600w"
sizes="(max-width: 768px) 100vw, 1200px"
alt="Description"
width="1600"
height="900"
/>
</picture>
This is the complete responsive-plus-format pattern. A framework can generate it automatically — see How to Implement WebP in Next.js with next/image.
How does responsive WebP affect Core Web Vitals?
Responsive WebP improves Largest Contentful Paint by sending small screens small files. A phone receives a 400px WebP instead of a 1600px JPEG, cutting the bytes for the LCP image dramatically. Always set width and height to reserve layout space and avoid Cumulative Layout Shift.
For the LCP image, add fetchpriority="high" and do not lazy-load it. The full performance treatment is in Core Web Vitals & Images.
Where to go from here
- How to Serve WebP Images in HTML Using the picture Element
- How to Implement WebP in Next.js with next/image
- Core Web Vitals & Images: Optimise LCP, CLS, and INP
- What is WebP? A Complete Guide to the WebP Image Format
- Convert your images: JPG to WebP, PNG to WebP
Resolution switching and format fallback are separate jobs. Use srcset and sizes for the right size, the <picture> element for WebP, and set dimensions to protect Core Web Vitals.