Responsive images using srcset
By Flavio
Tagged: HTML
Learn how HTML srcset serves responsive images, when to use x density versus w width plus sizes, and the common sizes mistake.
The srcset attribute of the img tag lets you list candidate images, so the browser downloads only what it needs. x descriptors (1x, 2x) pick a file by pixel density. w descriptors plus sizes pick a file by layout width.
Density with x
Use x when the image always occupies the same CSS size, like a logo or an icon. You ship one file per pixel density:
<img src="dog.png"
alt="A picture of a dog"
srcset="dog.png 1x,
dog-2x.png 2x">
A 1x screen loads dog.png. A 2x Retina screen loads dog-2x.png. src is the fallback if srcset is missing or ignored.
Do not mix x and w in the same srcset. Pick one system.
Width with w
Use w when the image’s layout width changes with the viewport. Here’s an example with four files of different widths:
<img src="dog.png"
alt="A picture of a dog"
srcset="dog-500.png 500w,
dog-800.png 800w,
dog-1000.png 1000w,
dog-1400.png 1400w">
The w descriptor is the image file’s intrinsic width in pixels. dog-500.png 500w means that file is 500px wide. The browser combines that with the slot size from sizes and the device pixel ratio to pick a file.
Without sizes, the browser assumes 100vw. Add sizes when the image is not full viewport width:
<img src="dog.png"
alt="A picture of a dog"
sizes="(max-width: 500px) 100vw, (max-width: 900px) 50vw, 800px"
srcset="dog-500.png 500w,
dog-800.png 800w,
dog-1000.png 1000w,
dog-1400.png 1400w">
sizes describes how wide the image will be displayed. The browser uses the first media condition that matches.
In this example the (max-width: 500px) 100vw, (max-width: 900px) 50vw, 800px string describes the display width in relation to the viewport, with multiple conditions separated by a comma.
If the viewport is narrower than 500px, the image is 100% of the viewport width.
If the viewport is bigger but still under 900px, the image is 50% of the viewport width.
If the viewport is even bigger, the image is 800px wide.
The vw unit of measure can be new to you. 1 vw is 1% of the viewport width, so 100vw is 100% of the viewport width.
For lazy-loaded images (loading="lazy") you can write sizes="auto" and let the browser use the image’s actual layout width. It only works together with loading="lazy". Support: Chrome 126, Firefox 150, Safari 27 (Safari has a bug with SVG plus object-fit).
Be careful with sizes. If you write 100vw for an image that sits in a 400px column, the browser thinks it needs a huge file and may download dog-1400.png on a phone.
srcset picks a different file of the same photo. If you need a different crop or a different format, use the picture tag.
A useful website to generate the srcset and progressively smaller images is https://responsivebreakpoints.com/.
You can also build the srcset and sizes attributes interactively with the srcset generator.
Want me to talk about your product? You can sponsor this site.