Responsive images in HTML

Developers working with responsive web design have a problem: <img> tags.

You can put an <img> in your markup and img {max-width: 100%} in your CSS, and the image will display as you want on small and large viewports, scaling to the width of its container. However, if your image has large dimensions like 800px wide and 600px tall (because it will be that wide on a large viewport like a desktop computer) but you’re viewing it on a small viewport like a phone, you’ll be wasting bandwidth and hurting performance by downloading that large file even though it’s being dramatically scaled down. It would be much better to have different sizes of the same image available and decide which one to use based on media queries.

Currently, HTML has no mechanism for doing this. There are some ingenious hacks out there, mostly involving server-side intercepts, cookies and JavaScript, but none are a real solution. Too many smart people are wasting too much time trying to get round this problem, and we need a way to deal with it natively in HTML. So, I’m proposing this (adapted from Bruce Lawson’s <picture> idea, and similar to how the <video> element works):

<adaptiveimg src="sweater-small.jpg" alt="Blue v-neck sweater in soft wool">
	<source src="sweater-medium.jpg" media="(min-width: 300px) and (max-width: 450px)">
	<source src="sweater-large.jpg" media="(min-width: 451px) and (max-width: 600px)">
	<source src="sweater-huge.jpg" media="(min-width: 601px)">
	<img src="sweater-small.jpg" alt="Blue v-neck sweater in soft wool">

Yep, another new element: <adaptiveimg>. It has the same attributes as <img>. It can contain one or more <source> elements, each with a media attribute containing a valid media query.

The user agent should cycle through each <source> element in order, updating the src of the <adaptiveimg> accordingly if the media query is matched. If there are no <source> elements, or none of the media queries are matched, the original src is used. Only after this logic has completed should the HTTP request for the image file take place (so there are no wasted downloads). The media queries I’ve used in the example are very simple, using just min-width and max-width, but in reality authors would often include other things such as device-pixel-ratio and color/monochrome.

Non-supporting UAs would simply ignore the new elements and render the fallback <img> as normal, but the structure would allow authors to implement a JavaScript polyfill if desired.

To be clear, all the <source>s should point to different sizes or arrangements of the same image — otherwise the content is being changed, which isn’t what we’re looking to do here. In other words, the same alt attribute should correctly describe all the <source>s.

Obviously there are a lot more details that would need to be worked out, but I think this is a good start, and I’ve sent it to Hixie and the WHATWG mailing list.

17th February 2012

There’s been a fair amount of discussion on the WHATWG mailing list, although at times it has felt like me, Matt Wilcox and Mat Marquis are just talking to each other. After a lot of feedback, mostly from the aforementioned two people, I’ve tweaked the proposal to remove its emphasis on the <img> element, which now becomes simply a fallback, and put attributes from <img> on <adaptiveimg>.

There were a few other ideas talked about, such as using a <srclist> element (a similar idea to <datalist> in Web Forms 2.0) and having an <alt> element within the new element for more “semantic” alternate text content. However, I think this core idea is the strongest, and we should push for it to be implemented by vendors (as Hixie has said before, they are the ones in control).