Did You Think Of Using CSS? - Responsive Images - Responsive Web Design, Part 2 (2015)

Responsive Web Design, Part 2 (2015)

Responsive Images

Did You Think Of Using CSS?

One of the earliest hacks to resolve responsive images was to turn content images into background images, and control the image resource using CSS media queries. In that technique, the <img> is replaced by a <div> and the image displayed is controlled using @media rules.

An example of that would be the following HTML:

<div id="content_image"></div>

accompanied by

#content_image {

background-image: url("cropped.jpg");

}

@media screen and (min-width: 50em) {

#content_image {

background-image: url("uncropped.jpg");

}

}

Only the required image21 will be then downloaded and displayed, enabling a hacky way to get art direction in place.

There are several problems with that approach:

•CSS becomes part of the content, and may incur frequent changes as content changes, rendering it non-cacheable in the long term.

•Accessibility is harmed, since there’s no way to define accessible alternatives to background images.

•Search engines will not recognize these images as content images, and will not include them in an image search.

•Performance is (often) harmed, since background images, usually defined in external CSS, require the entire CSS to be downloaded and parsed in order to be discovered by browsers.

That last point is also what prevented the adoption of any CSS-based responsive images proposal. Content images have always been discoverable at the early stages of the page’s loading cycle, and adding an extra delay for all the external CSS files to finish downloading and be applied will incur an excessive performance hit.

Did You Think Of Using JavaScript?

For obvious reasons, most of the initial hacks to tackle the responsive images problem were based on JavaScript.

The problem when using JavaScript to resolve this is that you have two less-than-ideal options: either delay the loading of images by eliminating their original src attribute; or incur a double download, where the initial src resource is downloaded and then replaced by a higher resolution or better fitting image.

That means that JS-based solutions suffer from a performance penalty, one way or the other.

Why Not A File Format?

A file format would be a great solution to most of the responsive images use cases, and I have given a lot of thought22 to how such a format might look, how would it work, and how can it be fetched by browsers.

Unfortunately, the downside of introducing a new file format is that it’s an excruciatingly slow process. Google has been pushing WebP for over four years now, with very little cross-browser adoption. Microsoft has been promoting JPEG-XR for even longer and with even worse results.

File formats (even if they’re just a wrapper around existing file formats, like the one I proposed) still need an ecosystem of authoring tools in place. It is also a field filled with intellectual property and patent claims, and the resulting FUD makes it difficult to introduce new formats without the backing of very large corporations. And even then, it’s slow.

With that said, I’m not ruling out a future in which a responsive file format can be incrementally fetched, with the help of HTTP/2.0, and resolve most of the use cases in an elegant way. It’s just not the world we live in today.

What About Background Images?

As we explored at the start of this chapter, the responsive images problem mostly referred to content images, because the background images angle was mostly covered. For art direction we had CSS media queries, which had no specific performance issues. They weren’t loading unnecessary resources, and didn’t have any delay penalty when compared to regular background images.

To address high-density screens, we had two options: either use media queries with the resolution media feature (or it’s non-standard predecessor device-pixel-ratio); or use the (WebKit-prefixed) image-set CSS feature. All in all, these were way more than what we had in the content images world (which was nothing), so the community didn’t put much focus on background images.

How, then, can we handle responsive background images today?

Say you need to add to your website a Retina background image (that would be loaded only on devices that need it, of course). You can get that done in supporting browsers by doing something like:

.hero-image { background-image: -webkit-image-set(url(1x.jpg) 1x, url(2x.jpg) 2x); }

The (prefixed) property is only supported by Safari, Chrome and Opera. The property is not currently supported by IE or Firefox.

Alternatively, if you need to art-direct the background image to specific breakpoint layouts, you can achieve that by using media queries and the @media rule:

.hero-image { background-image: url(narrow_viewport_crop.jpg); }

@media (min-width: 800px) {

.hero-image { background-image: url(wide_viewport_crop.jpg); }

}

Many have used the above technique over the years as a way to hack together some form of responsive images. As we’ve seen, we no longer need to do that, since nowadays we have proper responsive content images, and mixing our content images and our CSS is a bad practice for multiple reasons: performance, maintainability, accessibility, and SEO, to name a few.

But now, when the work on getting responsive content images support has calmed down, some focus is bouncing back23 to responsive background images, and matching their capabilities to those of content images. Specifically, there’s no way today to define a set of resources by their width and letting browsers pick the best one for the required display dimensions (like we do with w descriptors in srcset). MIME type switching is also a neglected use case in the background images world. Tab Atkins has proposed to add these use cases into the image-set specification24, and it looks like no one is opposing that.

It is too early to tell how far along that is in practice, or what would be the adoption rate from browser vendors once that becomes part of the spec.