Responsive Images Basics

srcset, sizes, and picture element

The term “Responsive Images” has been in common use for a while now. It refers to the ability to deliver the most appropriate image for the available viewport size, pixel density, even network connectivity.

For example, a Mac with a huge retina display is capable of displaying an extremely high resolution, large, image; whereas a phone in portrait mode on 3G may be better off with a smaller image – both in terms of dimensions and file size – which has been cropped to focus on the most important part of the image.

To achieve this required a significant amount of effort from the Responsive Images Working Group (RIWG) to help get functionality like the <picture> element and support for srcset and sizes attributes on both <picture> and <img /> into major browsers.

srcset

The srcset attribute allows us to define different sources for the same image, depending on the size and pixel density of the device’s display.

srcset’s “x” – pixel density (dpr)

So to display a different image for different pixel densities (e.g. standard definition or high def/retina) we might use something like:

<img src="img-base.png" 
    srcset="img-1x.png 1x, 
            img-2x.png 2x,
            img-3x.png 3x" />

The browser then decides which image to request based on the device capabilities (and potentially connectivity too).

srcset’s “w” – the actual image width

To display a different image for different screen sizes, we can give extra information to the browser about the actual dimensions of each image; the browser then uses this information to choose the “best fit”.

<img src="img-base.png" 
    srcset="img-120.png 120w, 
            img-240.png 240w,
            img-1200.png 1200w" />

So we can now let the browser know about the various images we have available (like a smorgasbord of images, if you will); the pixel densities and the actual image sizes.

However, the browser still has no clue as to how much space the image is expected to take up of the available display, at least not until all javascript and css has finished.

This is where sizes comes in –

sizes

We can let the browser know in advance how much of the screen we expect this image to take up such that it can make an informed decision when requesting the correct image:

<img src="img-base.png" 
    srcset="img-1x.png 1x, 
            img-2x.png 2x"
    sizes="(min-width: 36em) 33.3vw, 
            100vw" />

Here we’re letting the browser know that if the display is at least 36em, then the image will be used to fill one third (33.3vw) of the available width; if the screen is smaller than that then the image will cover the entire screen width (100vw).

Using sizes and srcset the browser can now decide which image it should request more easily.

picture

In the scenario where we want to display a potentially totally different image – or perhaps a cropped version of the normal one – there is the <picture> element:

<picture>
  <source media="(min-width: 900px)" 
          srcset="img-full.jpg">
  <source media="(min-width: 750px)" 
          srcset="img-cropped.jpg">
  <img src="img-mainonly.jpg" />
</picture>

In this scenario, we are telling the browser to use img-full.jpg if the display is at least 900px, img-cropped.jpg if the display is between 750-899px, and img-mainonly.jpg if it’s smaller than that.

This gives us the concept of art direction.

By your powers combined..

<picture>
    <source
        media="(min-width: 1280px)"
        sizes="80vw"
        srcset="img-full-1x.jpg 1x,
                img-full-2x.jpg 2x">
    <source
        media="(min-width: 800px)"
        sizes="100vw"
        srcset="img-full-200.jpg 200w,
                img-full-400.jpg 400w,
                img-full-800.jpg 800w,
                img-full-1200.jpg 1200w,
                img-full-1600.jpg 1800w">
    <img
        src="img-cropped-400.jpg" 
        sizes="(min-width: 640px) 60vw, 100vw"
        srcset="img-cropped-200.jpg 200w,
                img-cropped-400.jpg 400w,
                img-cropped-800.jpg 800w,
                img-cropped-1200.jpg 1200w">
</picture>

Hmm.. That’s getting pretty verbose. We can now handle multiple screen resolutions (in this example just for large screens), multiple image sizes (in this example just for medium sized screens), and art direction (in this example for small screens) with more than one possible display size.

The browser now has a significant amount of pertinent information in order to request the most relevant version of that image

However, we’ve gone from

<img src="img-full.jpg" />

with css to stretch or shrink an oversized image, potentially to code like the above.

Yes, it gives greater control, but it really feels cumbersome to me.

Hopefully this has been a useful intro to the HTML side of responsive images; my next article will demonstrate a newer, server-centric, option – client hints

Leave a Reply

Your email address will not be published. Required fields are marked *