Responsive images using srcset

By

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.

Related posts about html: