Responsive images with srcset

I think using srcset is the best way to serve responsive images on websites.

You could use the <picture> tag – and it does have it’s own benefits, but I prefer srcset – and of course you can combine using the <picture> tag with srcset.

srcset is capable of serving different images to your users based on the width of their browser window and their display’s pixel density.

It can’t do different formats – and that’s where you can combine it with the <picture> tag.

Pixel density example

Let’s start with the easiest example of srcset.

You need to serve different images for different pixel density displays.

In plain English, that means serving the normal image plus another that is twice the size for more pixel dense displays.

<img src="image@1.jpg" srcset="image@1.jpg 1x, image@2.jpg 2x">

You would use the example above like this:

  • The image is shown at 500x500px
  • image@1.jpg is 500x500px and is shown at 500x500px
  • image@2.jpg is 1000x100px and is shown at 500x500px

If you didn’t offer a bigger image, it’d look fuzzy on newer displays – including all Macs from 2010 and iPhones.

Different image sizes

You might show an image at different sizes based on the size of the user’s screen.

For example, a smaller image on a mobile device, a larger one on a tablet and an even bigger one on a desktop.

Of course, even a full width image would be smaller on mobile, larger on a tablet and larger again on a desktop. Always try to serve images at the same size they’re shown (accounting for pixel density) because it’ll make your site load faster.

Known image size

If we know the size of the image as shown on the webpage, then we can use the following code.

The image is shown at the following sizes (sizes):

  • 300px by default
  • 750px from a minimum screen width of 600px
  • 1000px from a minimum screen width of 900px

We need specify the available images (srcset):

  • 300px – the default image
  • 600px – the default image for a pixel density ratio of 2
  • 750px – for screen widths over 600px
  • 1500px – for screen widths over 600px with a pixel density ratio of 2
  • 1000px – for screen widths over 900px
  • 2000px – for screen widths over 900px with a pixel density ratio of 2

Here’s the code.

<img
	src="image-300.jpg"
	sizes="(min-width: 900px) 1000px, (min-width: 600px) 750px, 300px"
	srcset="image-300.jpg 300w, image-600.jpg 600w, image-750.jpg 750w, image-1000.jpg 1000w, image-1500.jpg 1500w, image-2000.jpg 2000w"
/>

The line breaks are just for legibility.

Based on the viewport

If you don’t know the precise size of the image, because it’s the full width of the screen for example, you can use the following code.

<img
	src="400.png" 
	sizes="(min-width: 600px) 25vw, (min-width: 500px) 50vw, 100vw"
	srcset="100.png 100w, 200.png 200w, 400.png 400w, 800.png 800w, 1600.png 1600w, 2000.png 2000w"
/>

So here, you’re saying to the browser that:

  • if the screen width is at least 600px, the image is a quarter the width of the screen,
  • if the screen width is at least 500px, the image is half the width of the screen,
  • or else it’s the full width of the screen.

The browser then chooses the most appropriate image from the sizes attribute, taking into account pixel density too.

Different formats

You might want to offer images at different sizes and formats.

I’d recommend you do, offering images in WebP and AVIF formats can save on bandwidth and speed up your website, because you can offer an almost identical looking image at smaller file sizes.

This is easier than you’d think. The hard bit is getting your head about srcset and sizes.

Now that you have, you can use srcset and sizes on the <img> and <source> tags below.

<picture>
	<source
		type="image/webp"
		sizes="(min-width: 900px) 1000px, (min-width: 600px) 750px, 300px"
		srcset="image-300.webp 300w, image-600.webp 600w, image-750.webp 750w, image-1000.webp 1000w, image-1500.webp 1500w, image-2000.webp 2000w"
	/>
	<img
		src="image-300.jpg"
		sizes="(min-width: 900px) 1000px, (min-width: 600px) 750px, 300px"
		srcset="image-300.jpg 300w, image-600.jpg 600w, image-750.jpg 750w, image-1000.jpg 1000w, image-1500.jpg 1500w, image-2000.jpg 2000w"
	/>
</picture>

The example above serves a WebP version of the responsive image if that’s supported by the browser and falls back to JPEG if not.

The picture tag tries the first <source> tag and if it can’t use that, it moves on to the next <source> tag and finally the <img> tag.

max-width

You can use max-width in your sizes attribute too.

Note when we use min-width we start with the largest sizes and work our way down, we do the opposite with max-width.

Like this:

sizes="(max-width: 500px) 400px, (max-width: 900px) 800px, 1000px"

Share