How to optimize your images: Part 1 - The srcset attribute

  • Engineering
  • Guides
In the first of a series, we look at how to use standard HTML features to deliver the right image for the right conditions.
6 mins reading time
Neil Cooper | January 15, 2021

70% of webpage payload is images, and webpage performance (in simple terms - download speed) is tightly linked to the file size of those images. It's been well established in studies that slower render times impact engagement and conversion. 

Therefore it's very important that the images on your website are well optimized. This has its challenges, and developers face a myriad of different factors that affect image delivery. In the early 2000s, smartphones introduced completely different form factors, with both portrait and landscape viewport measurements, that differed from the then ubiquitous desktop setup. Throw in retina displays, more modern image formats, a widening gap between the slowest 2G connection and ultrafast 5G, and developers face a bit of a nightmare.

Fortunately, there is a pretty well supported set of features within HTML5 that allows developers to get around more or less all of these problems and deliver the right image for the conditions. 

This is the first in a series of blog posts that cover image optimization, starting with standard HTML image support. In later parts of the series we'll explain how to take things further by taking advantage of the features of Amplience Dynamic Media. 

Image tags

If you're going to be serving images within a webpage then you need an image tag:

1<img src="cat.jpg" border="0" alt="a picture of my cat" />

This works- it's standard HTML and it's supported by every browser. Nothing is stopping you from adding some CSS styles to this and squashing/stretching the image as required for different browser viewports. But, this leaves you with a bunch of decisions to make. If you choose an original image that's too small then it's going to look terrible stretched up to the larger dimensions for a 20+ inch retina display. If you choose too large an original image, then a mobile user on a slow connection is probably never going to manage to download the image before they give up.

As you can see in the example above, the same 275KB image could take almost 7.5 seconds to load on a slow mobile connection (the original size is 1280x854).

Srcset

It's possible to give the <img> tag multiple images and allow the browser to choose which of these images to display based on what it knows about the device. We do this using the srcsetattribute and pixel density descriptors:

1<img src="cat.jpg" srcset="cat.jpg 1x, cat2x.jpg 2x, cat3x.jpg 3x......cat16x.jpg 16x" />
Of course, you'd have to create/provide suitable images for each of the cases you want to support, which is one place where some CDNs and DAM providers come in, rather than having to manually create all those versions, you can supply one high fidelity source image and let them do the work. The following example uses the image width parameter of the 

Amplience Dynamic Media image API.

1<img src="/cat.jpg?w=300" srcset="cat.jpg?w=300 1x, cat.jpg?w=600 2x, cat.jpg?w=900 3x... 16x" />

This works fine if your images are a fixed width, but what if you're scaling them, or using relative units like percentages or ems, which does the browser choose?

Width descriptors and sizes attribute

This is where width descriptors come in. Simply they inform the browser the width of the source image:

1<img src="/cat.jpg?w=300" srcset="cat.jpg?w=300 300w, cat.jpg?w=600 600w, cat.jpg?w=900 900w" />
But, how does the browser know the width that it should choose? You can use the sizes attribute to provide the browser with more information:
1<img src="/cat.jpg?w=300" srcset="cat.jpg?w=300 300w, cat.jpg?w=600 600w, cat.jpg?w=900 900w....." size="(min-width: 1681px) 1680px, 100vw" />

Now we've instructed the browser that for any widths 1681px and above we need the image with a width of 1680px. If that condition isn't met (for example, for a width of 1680px or less) the width should be 100% of the viewport width- this value is readily available to the browser.

The browser uses this information, combined with the device pixel ratio, and any other available factors, to choose one of the images from the srcset attribute.

In our example, for a viewport 375px wide on with a pixel ratio of 2, we'd be below the 1681px media condition, so our width would be 375px, but because the pixel ratio is 2, we need an image with an original width of 750px (2 x 375). In this case the browser would select the first source that met that condition: 600w is too small, so it will choose the 900w and squash the image down to the appropriate size.

By being clever with your srcset values and image optimisations you can do a lot to ensure that the most appropriate image is chosen, without too much stretching of a small image, or squashing down of a large one. A little analysis of your website traffic can give you a good enough list of what image sizes are being requested by your end users and allow you to create a sensible list of image options for the browser to choose from. With a CDN/DAM provider in place, there's little extra work other than determining the optimum list of widths to support.

So now we can request the right size image for our browser/device. What else do we need? In Part 2 we'll take a look at a more advanced solution to the image optimization puzzle: picture tags.