Responsive images with srcset and sizes

, by Wouter van der Zee

With the new attributes srcset and sizes for the <img> tag, you can specify multiple sizes of the same image. The browser chooses the best size for each situation. This will help serving better images for your users and improving the loading time of your website.

These new attributes are available for some time now. However, I didn't manage to understand it fully. There are great articles on the web explaining this new syntaxLike the great article 'Srcset and sizes' from Eric Portis. But I couldn't wrap my head around it. And especially, I missed in those articles how one could apply srcset and sizes to real world problems.

So, that's why I wrote this article about srcset and sizes. It comes with an example of a common website layout: a page with sidebar. I hope it will help you better understand srcset and sizes and how to apply it to your website projects.

Why using srcset and sizes?

Let’s start with the beginning. Why even use srcset and sizes? I see two advantages:

  • serving better images to the user,
  • improving the website loading time

With srcset and sizes it is possible to offer multiple sizes of the same image. The browser does the calculation (yeah!) and chooses the best size to display to the userBrowser support for srcset and sizes is good, but the fallback even better..

The browser not only takes into account the width of the screen (viewport width), but also the pixel density. Whether a user is viewing your website on a desktop screen with low resolution or a tablet screen with high resolution, the browser chooses the best size.

Because you can offer multiple sizes of the same image, you can improve the loading time of your site. It’s no longer needed to serve that big hero image on a small screen. With srcset and sizes you can offer a smaller size which will be used by the browser. This results in a faster website. And most users will appreciate that very much!

I think we have sufficient reasons to get acquainted with srcset and sizes.

How srcset and sizes works

An example of an <img> tag with the new srcset and sizes attributes:

<img alt="image alt text" src="medium.jpg" srcset="small.jpg 240w, medium.jpg 300w, large.jpg 720w" sizes=“(min-width: 960px) 720px, 100vw">

To make it a little easier to read:

<img
   alt="image alt text"
   src="medium.jpg"
   srcset="
      small.jpg 240w,
      medium.jpg 300w,
      large.jpg 720w
   "  
   sizes="
      (min-width: 960px) 720px,
      100vw
   "
>

Let us walk through each part.

alt="image alt text"

As with each <img> tag, you just use the alt text.

src="medium.jpg"

The familiar way to specify the location of your image. Browsers that do not support srcset and sizes will fallback to src.

srcset="small.jpg 240w, medium.jpg 300w, large.jpg 720w"

This is where the magic begins. With scrset you specify a list of the image in different sizes. In this example we have three sizes of the same image. Behind the file name of each image you specify the width in pixels (w of width). For example, small.jpg 240w means that this image is 240px wide.

sizes="(min-width: 960px) 540px, 100vw"

With sizes you specify the size of the image and in which situation it must be displayed. This is done by a combination of a media query and the the width of the imageFor the width of the image in sizes you can use different values like px, em, vw etc.. See the list of available values on w3.org. For me, sizes was the most difficult part to understand. But I think it’s also the most powerful one.

The above code for sizes does the following:

  • if viewport width equals to 960px or greater than show the image with a width of 540px,
  • if the viewport width is smaller than 960px than show the image as wide as the viewport (100vw means 100% of the viewport width).

Now you may notice that in our example of srcset there’s no image with a width of 540px. That’s not a problem. The browser will select the best image available upwards in size. In this case, large.jpg will be used with a width of 720px.

HD and Retina screens

On ‘normal’ screens, using the viewport width seems sufficient to choose the correct size of the image. But with HD and Retina screens you want to serve bigger sizes of the image. Et voilá, here comes srcset and sizes! With srcset and sizes the browser also takes into account the pixel density of the screen.

To calculate the pixel density of a screen, browsers make use of the pixel-device-ratio. A pixel-device-ratio of 1 means that one device pixel corresponds to one CSS pixel. A pixel-device-ratio of 2 means that two device pixels corresponds to one CSS pixel.

For example, an iPad Air 2 has a screen resolution of 2048 by 1536 pixels (source: Wikipedia). The pixel-device-ratio of this iPad is 2. Which means that for the browser, the screen is 1024 by 768 pixels.

Let’s see if this all works for a real world example.

Example: page with sidebar

For this example, I’ve choosen a common website layout: a page with a sidebar. I’ll look through three situations: viewing this page on mobile, tablet and desktopThe media queries in this example are based on said devices. I did that to make the example easier. For your projects it’s best practice to base your media queries on the site layout.. In addition, the following applies:

  • the width of the page content is 67%, the sidebar is 33%
  • on mobile, the sidebar is displayed below the content,
  • mobile and tablet have a pixel-device-ratio of 2
Example for srcset and sizes: a page with sidebar.
Example for srcset and sizes: a page with sidebar.

Mobile

When this layout is viewed on mobile, we get the following result:

  • viewport width is 320px,
  • pixel-device-ratio is 2,
  • the number of actual pixels is therefore 320px x 2 = 640px,
  • the sidebar is displayed below the content at full screen width,
  • we therefore need an image of 640px wide,
  • and sizes is set to 100vw

Our preliminary HTML for srcset and sizes:

srcset="small.jpg 640w" 
sizes="100vw"

Tablet

On a tablet, we get the following result:

  • viewport width is 768px,
  • pixel-device-ratio is 2,
  • the number of actual pixels: 768px x 2 = 1536px,
  • the sidebar is displayed right of the content,
  • the width of the content is 67%,
  • the width of the image is 67% of 1536px = 1030px,
  • sizes can be set as: (min-width: 1536px) 1030px For this example, I set the sizes media queries equal to the size of the image. For your projects it’s better choosing media queries that take into account the entire site, not just this image.,
  • that means something like: is the viewport width 1536px or higher, show the image with a width of 1030px

This brings our HTML to look as follows:

srcset="
   small.jpg 640w, 
   large.jpg 1030w
"
sizes="
   (min-width: 1536px) 1030px,
   100vw
"

Desktop

The final situation where we want to load the correct image size is desktop. I’ve picked a display with a resolution of 1366 x 768pxAccording to the statistics of w3schools.com that is a common resolution at this moment..

This results to:

  • the viewport width is 1366px,
  • the pixel-device-ratio is 1,
  • CSS pixel width is 1366px x 1 = 1366px,
  • the width of the content and the image is 67%,
  • the width of the image is 67% of 1366px = 916px,
  • for sizes we get: (min-width: 1366px) 916px,

Adding this to our ‘srcset` and ‘sizes’ we get:

srcset="
   small.jpg 640w,
   medium.jpg 916w, 
   large.jpg 1030w
"
sizes="
   (min-width: 1366px) 916px,
   (min-width: 1536px) 1030px,
   100vw
"

To complete the <img> tag for this example, let’s add the attributes alt and src.

<img
   alt="alt text image"
   src="medium.jpg"
   srcset="
      small.jpg 640w,
      medium.jpg 916w, 
      large.jpg 1030w
   "
   sizes="
      (min-width: 1366px) 916px,
      (min-width: 1536px) 1030px,
      100vw
   "
>

In summary, this code does the following:

  • it serves small.jpg when viewed on mobile,
  • it serves medium.jpg when viewed on desktop,
  • it serves large.jpg when viewed on a tablet

I think that’s well done!

Comments

It seems that the difference between medium.jpg and large.jpg is not big. Why not use the same image for both situations, e.g. large.jpg?

Well, the difference is greater than you think. Let’s assume that the image size has a ratio of 3:2 (length:width). Then large.jpg is 21% larger in size than medium.jpg The calculation is as follows. The area of medium.jpg is 916px x 614px = 562.424px, that of large.jpg is 710.700px. Thus, the surface area of large.jpg 21% greater.. Using both sizes is certainly worth it.

Browser support for srcset and sizes

Browser support for srcset and sizes is good, but not excellent. Globally, ca. 83% of the browsers support srcset and sizes. It is not supported by Internet Explorer, Opera Mini and older versions of Android. But remember, the fallback is perfect. If srcset and sizes is not supported, the browser will use the src attribute.

Check browser support for srcset and sizes on caniuse.com.

Browser support for srcset and sizes according to caniuse.com (Nov. 11, 2016).
Browser support for srcset and sizes according to caniuse.com (Nov. 11, 2016).

Sources

The following articles inspired me writing this post:

Also published on Medium.com.

Comment on Twitter