Responsive Images Revisited—The Srcset Attribute

One of the main challenges with responsive design is how to handle images. It’s not that we don’t know what we want to do. It’s that the ability to do it has been lacking. Fortunately the situation is starting to change for the better.

The Source

Like many designers, I’ve sat on the sideline waiting for responsive images to sort themselves out. In previous looks at how to solve responsive image problems, I walked away with the feeling that the solutions were usually more trouble than they were worth for myself and my typical clients.

For larger organizations it makes sense to put better solutions in place, but for most people, the benefits don’t justify the time, effort, and budget. Since neither my clients nor myself are large organizations, it made sense to wait out the spec and technology to see what they would bring.

The good news is the spec is finally coming together. After reading a recent post by Jason Grigsby about picture and srcset, I thought now would be a good time to revisit the topic of responsive images.

It turns out there was more to cover than I thought so this will be a multi-week topic. Today I’ll cover some background, history, and browser support, before digging into the srcset attribute and the associated sizes attribute.

In coming weeks we’ll look at the picture element and which method is best to use when. I have a demo planned as well as a few additional topics and general thoughts about responsive images.

A Bit of History

In case you aren’t familiar with some of the history behind responsive images, particularly in regards to new specifications in html to handle them, I’ll try my best to summarize.

Since the beginning there have been two camps with different approaches to switching images. Browser makers support srcset in large part for performance reasons. By allowing browsers to make the decision, browser can optimize them.

Designers and developers, on the other hand, have generally supported the picture element, because the syntax is more natural and because the picture element gives us control instead of leaving it with browser makers. Both approaches have their merits and as well as their difficulties.

The srcset attribute has more often been “winning” this battle and for a time it looked like the picture element would never arrive. In the end we’re getting both srcset and picture giving us tools to solve some of the basic issues around working with responsive images.

Browser Support, Polyfills, and Testing

At the moment browser support isn’t great, but support is coming and, given the importance, I’ve no doubt that very soon the latest versions of all browsers will offer support. As I’m writing this here’s how things break down.

The srcset attribute is supported in the latest versions of Chrome, Opera, Android Browser, and Chrome for Android. Safari offers partial support. It doesn’t support the sizes attribute, which can be used in conjunction with srcset. Firefox, Internet Explorer, and Opera Mini offer no support.

The picture element has a little less less support. It works in full in the latest versions of Chrome, Opera, and Chrome for Android. No other browser currently offers even partial support.

Things do seem to be moving quickly and I expect browsers to be supporting both srcset and the picture element sooner rather than later. Don’t let the current lack of support keep you from using srcset and picture, though. Scott Jehl maintains the picturefill polyfill on GitHub. It has support for srcset, the picture element, and associated tags and attributes.

One issue you may have is testing high DPI images. I know it’s an issue for me. My tablet and phone can handle @2x images, but the hardware is moving on to @3x. My laptop is @1x only. One method for testing is to visit stores selling the devices you want to test on, however there are some other approaches.

The developer tools in browsers have gotten quite good and some can be adjusted to let you test high pixel density images. Here’s some information I found for testing high density images.

I can’t honestly say they work. I only tried in Chrome and my developer tools looked different than these screen shots I saw.

I was able to work out testing in Chrome, though. Zooming to 200% and reducing the default font-size from 100% to 50% in my style sheet, effectively simulates @2x resolution. Matt Zeunert also has a nice article with general Cross browwer testing advice, including some thoughts about pixel density in browsers.

I’m not sure if Internet Explorer offers a similar way to set pixel density. The best I’ve been able to find is resetting the dpi scaling in Windows itself. If someone knows more please leave a comment so I can add IE testing here.

How the srcset Attribute Works

The basic idea behind the srcset attribute is you provide information to browsers to help them decide which image to display based on the pixel density of both image and screen. Letting browsers build algorithms to choose will make for faster choices in which image(s) to show.

You add the srcset attribute to an <img> tag like you see in the example below.

1
2
3
<img src="default-image.jpg"
     srcset="image-1.5.jpg 1.5x, image-2.0.jpg 2x"
     width="600" alt="My image">

Other than the srcset attribute, it’s an ordinary <img> tag with src, width, and alt attributes. The src sets a default image, which will be used by non-supporting browsers (they ignore srcset) and may be used by supporting browsers depending on conditions.

The srcset attribute contains a list of images along with the display density of that image. Note that it’s a single attribute with a comma separated list of images and densities. If you create a @3x image, you’d add it to the end of the list.

Browsers then uses a little math to figure out which image to use. Say a device that’s 320px wide is loading the page in question. 600px (the image width) divided by 320px (the screen width) results in a value of 1.875. Ideally an image with this density is provided in the list, but since one isn’t, the browser would decide if a 1.5x or 2.0x image would be the better image to display.

That’s the simplest case, where the only thing that needs changing is the resolution of the image. However, with responsive design we know the sizes of those images will also change to fit within a changing layout. Enter the sizes attribute.

The sizes Attribute

The sizes attribute gives you the ability to tell browsers to select different images based on their size and how much of the viewport they’ll occupy.

The ideal would be to let browsers choose like they do for resolution differences, but the image dimensions that get used would require knowing the page layout first. Browsers can do this, but if we give them some information up front we can save them time and keep them from downloading more images than necessary.

1
2
3
4
5
<img sizes="100vw"
     srcset="width-400.jpg 400w,
             width-800.jpg 800w,
             width-1600.jpg 1600w"
     src="width-400.jpg: alt="My image">

The code above isn’t all that different from the previous example. Starting at the bottom, there’s a default image on the src attribute as well as an alt attribute.

The scrset attribute (above the src) is similar to the previous example in that it’s a comma separate list of images plus something else. Instead of 1.5x, 2x, 3x we now see 400w, 800w, 1600w. The w values are telling browsers this image is 400px wide, 800px wide, etc.

The sizes attribute (note the plural sizes) contains the information you give browsers so they can choose an image. In this code sizes has a single value of 100vw, which means an image should fill 100% of the viewport width. 100vw is the default, by the way, if no value is set.

Once again the browser does some math. Since the size is defined as 100% of the viewport it’s the same math as before (image width ÷ screen width = pixel density). Let’s say a device that’s 600px wide lands on the page.

  • 400/600 = 0.67
  • 800/600 = 1.25
  • 1600/600 = 3.20

The browser would then choose the best image based on the above results and the pixel density of the screen. The sizes attribute may not seem all that exciting, until you realize you aren’t limited to a single size as an attribute value.

1
2
3
4
5
6
7
8
<img sizes="(max-width: 30em) 100vw,
            (max-width: 50em) 50vw,
            33vw"
     srcset="width-200.jpg 200w,
             width-400.jpg 400w,
             width-800.jpg 800w,
             width-1600.jpg 1600w"
     src="width-400.jpg" alt="My image">

In the code above there are three possible sizes along with the srcset images and the default/fallback image. A browser open to 30em or less would use 100vw. A browser open more than 30em, but not more than 50em uses 50wv. Browsers wider than 50em will use 33vw. From there the math is the same.

Assuming 1em = 16px, imagine a viewport of 800px and 2x density is rendering the page. The viewport is 50em so it’ll use the second sizes value, which is 50vw. Half 800px is 400px, which gets used in the calculations.

  • 200px/400px = 0.5
  • 400px/400px = 1.0
  • 800px/400px = 2.0
  • 1600px/400px = 4.0

Since the screen has 2x pixel density, the 800px image would likely be chosen in this scenario.

Ultimately the sizes attribute allows more flexibility in what image(s) you want to display based on both viewport width and resolution, instead of resolution alone. However, you’re still letting browsers make the decision for which image to show.

Sometimes you want to make that decision yourself, which brings us to the picture element and next week.

Closing Thoughts

It didn’t take designers long to realize there were issues that needed to be solved when working with responsive images. Most of the solutions to this point have been too complicated, time consuming, and expensive for most people to implement. They’ve remained the domain of larger organizations with more resourcesfor the most part.

What many designers have been waiting for are new specs that make it easier to work with images in responsive layouts. It’s taken some time and lots of battling, but the spec is becoming clearer and browsers are beginning to support the srcset and sizes attribute along with the picture element.

The srcset attribute is a simple way to suggest different images to browsers based on their pixel density. In combination with the sizes attribute it can be used to suggest which image a browser should use based on image and viewport size as well as pixel density.

However, both leave the final decision up to the browser. That’s a good thing because it allows browsers to find and download the best image quicker, but sometimes we want to make the selection ourselves.

The picture element lets you do just that. Next week I’ll pick up this conversation with a look at the picture element and how it works. I’ll also talk about when to use srcset and when to use picture based on what you’re trying to do.

Download a free sample from my book, Design Fundamentals.

Leave a Reply

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