Bitmaps with HTML5

Before deciding on which technique to use you need to decide what you want to achieve.

  1. Do you want your images to stay the same size, but look good on high resolution displays? Choose resolution switching only.
  2. Do you want your image to look good on high resolution displays and change size? Perhaps you want them to decrease in size with the screen width, for example. Use the w descriptor and the sizes attribute.
  3. Do you want to swap your image for another one at different screen widths? Perhaps you have a photo of a crowd of people which works fine on large screens, but when it is squished down on a small screen the people look blurry. You might want to swap the image for a cropped version that only shows three people. If so, you want the picture element.

1. Resolution switching (srcset and the x descriptor)

Use this when you want your image width to stay the same in proportion to the page. In this example I've made three versions of the same image: 300px, 600px and 900px wide. They are then associated with 1x, 2x and 3x pixel densities respectively.

Human Data meeting
<figure>
  <img src="images/example-image-300px.jpg"
    srcset="images/example-image-300px.jpg 1x,
    images/example-image-600px.jpg 2x,
    images/example-image-900px.jpg 3x"
    alt="Human Data meeting"/>
</figure>

The browser chooses the best image for the pixel density of the display. 1x equates to the pixel density seen on a 96 dpi display (a traditional desktop display). 2x is double this display density (like iPhone 6, Retina Macs, Galaxy S3), and 3x triple the display density (like on iPhone 6 Plus and 7, and Galaxy Note III).

Remember: in this technique the image stays the same width across screen sizes, and you need to know the display density of the devices you are targeting. Also srcset is not supported by IE or Edge.

2. The w descriptor and the sizes attribute

Do this when you want your image to change sizes across different screen widths. Let's look at an example.

Human Data meeting
<figure>
  <img src="images/example-image-300px.jpg"
    srcset="images/example-image-300px.jpg 300w,
    images/example-image-600px.jpg 600w,
    images/example-image-900px.jpg 900w"
    sizes="(max-width: 480px) 100vw, 300px"
     alt="Human Data meeting"/>
</figure>

First we use the src attribute to give a default image to browsers that don't support srcset. Then we include the same images as before, except with a w descriptor after them. This lets the browser know how wide the images are before it has downloaded them (600w = 600px).

The sizes attribute tells the browser how wide the image should be at different screen sizes. It works a bit like media queries. So in our example we're saying "At screen widths below 480px make the image 100% of the viewport width (vw). For bigger screen sizes just make the image 300px wide." The browser also chooses the best version of the image for the display density, so you still get sharp images, as in resolution switching.

Try resizing your browser window to see the change in image size at small screens. Of course you can specify more breakpoints than the one at 480px.

The picture element

This allows you to use different crops of an image, or different images, at different screen sizes. In this example we've set break points in the <source> tag and we deliver a different version of the image at each break point.

For wide screens (min-width: 960px) you see six people, then between 700x and 960px you get a version of the image that shows four people. Below 700px you get a version of the image that shows three people. Notice that we're also using resolution switching.

Human Data meeting
Count the people as you resize your browser window!
<figure>
  <picture>
    <source
    srcset="images/example-image-300px.jpg 1x,
    images/example-image-600px.jpg 2x,
    images/example-image-900px.jpg 3x"
    media="(min-width: 960px)">

    <source
    srcset="images/example-image-300px-cropped2.jpg 1x,
    images/example-image-600px-cropped2.jpg 2x,
    images/example-image-900px-cropped2.jpg 3x"
    media="(min-width: 700px)">

    <source
    srcset="images/example-image-300px-cropped.jpg 1x,
    images/example-image-600px-cropped.jpg 2x,
    images/example-image-900px-cropped.jpg 3x">

    <img src="images/example-image-300px.jpg" alt="Human Data meeting" />
  </picture>
  <figcaption>Count the people as you resize your browser window!</figcaption>
</figure>

Which approach to use?

Apart from which use case you have (see the questions at the top of the page) bear in mind:

  • You need a system that can automatically crop images into different sizes. If you don't there are online services like:
    • imgix: you store your images elsewhere (your server or the Amazon Cloud) and imgix chops them up for you. You link to the images using an imgix url.
    • Cloudinary: stores your images and crops them for you.
    • Responsive Image Breakpoints: crops your images for you and you download the images. It provides the code you need to display the image. You need to manually upload and download each image, though.
  • You need large images to start with. In the desktop world, if you wanted an image 300px wide you just needed a 300px wide image. With these techniques you need one at least 900px wide.

elixir-europe.org is moving towards approach 1 (resolution switching), although the ability to use all approaches would be ideal.