Responsive Images the Simple Way

The logic behind displaying an image responsively is complicated. It involves determining how large the image will be displayed, as well as understanding whether the user is on a high-resolution display, among other things. Thankfully, the browser is better equipped than we are to handle this logic. All we need to do is give it some hints. We’ll use the srcset attribute to provide a list of image assets to choose from, and the sizes attribute to tell the browser how large the image will display at various breakpoints.

Yes, the syntax is still the same as in 2014, but it’s good to be remembered of it … I always find myself looking things up again when it comes to Responsive Images 😬

Responsive Images the Simple Way →

SVG and <picture>

<picture>
    <!--[if IE 9]><video style="display: none;"><![endif]-->
    <source type="image/svg+xml" srcset="path/to/header--full.svg">
    <source type="image/svg+xml" srcset="path/to/header--medium.svg" media="(max-width: 1024px)">
    <source type="image/svg+xml" srcset="path/to/header--small.svg" media="(max-width: 640px)">
    <!--[if IE 9]></video><![endif]-->
    <img src="path/to/header-1x.png" srcset="path/to/header-2x.png 2x, path/to/header-3x.png 3x" alt="Header description">
</picture>

Besides using an SVG as a background image in CSS, you can serve SVG foreground images in HTML using one of several embedding techniques, each of which has its advantages and use cases. Unless you’re in need of interactivity or external styling, <img> is the standard way for loading an SVG image, but it has one disadvantage: you currently need JavaScript to provide fallback and/or change the image source for art direction. In this post, I’ll talk about a better way to do that, using the <picture> element.

Don’t forget to include PictureFill 😉

Better SVG Fallback and Art Direction With The <picture> Element →

Not familiar with <picture>? Be sure to read Introducing the <picture> element and Native Responsive Images first.

Responsive Images in Practice

<img 
    srcset="quilt_3/large.jpg  1240w, 
            quilt_3/medium.jpg  620w,
            quilt_3/small.jpg   310w"
    sizes="(min-width: 41.25em) 38.75em,
           calc(100vw - 2.5em)"
    src="quilt_3/medium.jpg"
    alt="A crazy quilt whose irregular fabric scraps are fit into a lattice of diamonds." />

Let’s take an existing web page and make its images responsive. We’ll do so in three passes, applying each piece of the new markup in turn:

  1. We’ll ensure that our images scale efficiently with srcset and sizes.
  2. We’ll art direct our images with picture and source media.
  3. We’ll supply an alternate image format using picture and source type.

In the process we’ll see firsthand the dramatic performance gains that the new features enable.

A List Apart: Responsive Images in Practice →

Picturefill 2.0 alpha

<picture>
	<source srcset="examples/images/extralarge.jpg" media="(min-width: 1000px)">
	<source srcset="examples/images/large.jpg" media="(min-width: 800px)">
	<source srcset="examples/images/medium.jpg">
	<img srcset="examples/images/medium.jpg" alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia">
</picture>

The picture element and associated features are W3C standard HTML features that allow web developers to deliver an appropriate image to every user depending on a variety of conditions like screen size, viewport size, screen resolution, and more. Picturefill is a polyfill that enables support for the picture element and associated features in browsers that do not yet support them, so you can start using them today!

A consensus was reached on the spec. Chrome, Firefox, and Opera are implementing it as we speak. Until then (and for other browsers) use this one.

Picturefill →

Focal Point: Intelligent Cropping of Responsive Images

When working with images on small screen devices it is recommended to focus on the subject: don’t just show a scaled down version of the photo, it’s better to remove some of the background scenery and show the person on the photo (see the Obama example at the top of this post on responsive images).

Enter Focal Point:

A small set of CSS classnames to help keep images cropped on the focal point for responsive designs. Using only HTML/CSS, web authors can specify an image’s focal point, which stays as the image’s primary focus, while the image’s available width changes on responsive webpages. Crop and re-size images depending on available width and let CSS to do all of the work, and without any JavaScript

Yes, pure CSS that is 🙂

Focal Point Demo →
Focal Point Source (GitHub) →
Focal Point Article →

Retinafy your web sites & apps

Now that phones, tablets and laptops use high-resolution, “can’t tell it’s pixels” displays it’s time to take the plunge and make your sites and apps ready for retina.

With my ebook you’ll be up to speed in no time, with easy to follow step-by-step instructions on creating stunningly beautiful high-resolution websites, that load fast and work in any browser

By Thomas Fuchs.

Retinafy.me →

Responsive images: Current state & overview

Responsive images is a surprisingly complicated topic, and one that’s been steadily gaining attention over the last year as more developers discover they need them and then discover there’s no good solution yet. This article aims to give an overview of the problem itself, and show the different proposals in the works to address it.

Good summary if you want to catch up or didn’t find the time to follow the W3C Responsive Images Community Group blog

Responsive images: what’s the problem, and how do we fix it? →

Pngy – Load images based on network connection speed

Pngy is a bit of jQuery that allows you to load images of different file sizes based on a page’s load speed. So, if the load speed is slow, Pngy can load your small image. If it’s fast, it can load a hi-res image. It’s kinda like a ping test in Javascript.

Resonates with my ideas on responsive images

Pngy (GitHub) →

jQuery Anystretch

Anystretch is a jQuery plugin that allows you to add a dynamically-resized background image to any page or block level element. The image will stretch to fit the page/element, and will automatically resize as the window size changes.

Handy when having a fluid layout/responsive design.

Anystretch Demo →
Anystretch (GitHub) →

UPDATE: Reader Oemebamo pointed out that this can be achieved with CSS, using background-size: cover;. Turns out background-size is widely supported (thought it was Chrome only).

The slow elephant in the responsive images room

The past few weeks a lot has been going on around one of the challenges of responsive web design, namely responsive images. The gist of it is pretty straightforward: it’s not a good idea to let a device download a big image if that device is a small-screen device. It’s better to serve that device an image that (approximately) fits its screen.

As it turns out we cannot use the current tools/tags we have to solve this problem, we are in need of a proper solution. Ergo, a community group was brought to life to wrap their heads around the problem.

Proposals

A current proposal that is getting quite the attention is to introduce a <picture> element with some various <source> children, this inspired upon how <video> and <audio> are coded. Key difference though is that you explicitly define the minimum (or maximum) required width along with it.

<picture alt="Alt tag should accurately describe the image represented by all sources, though cropping and zooming may differ.">
    <source src="mobile.jpg" /> <!-- Matches by default. -->
    <source src="high-res.jpg" media="min-width: 800px" /> <!-- Overrides the previous source over 800px before any assets are fetched, resulting in a single request. -->
    <img src="mobile.jpg" /> <!-- Fallback content, in the event the <picture> tag is completely unsupported by the user's browser. -->
</picture>

An other proposal that I quite dig is a new image format that acts as a container and can hold several images inside it. Think of it as a .zip with some images inside it (or if you’re familiarized with OS X: a .icns file). The implementation could be done in such a manner that the browser only downloads the wanted size based upon it’s screen size.


Inspection of an .icns file, image by http://mistermorris.tumblr.com/

Faux Responsive Images

Until one of these ideas — or any other great idea that could possibly provide an answer — is actually implemented, there are some techniques that we can use right now to mimic responsive images, but they’re not all good (hence the need for the community group).

One that caught my eye though — because of its pure simplicity — is Responsive Enhance: Serve the browser a low-res image. If more screen estate is available, let it pull in a high(er) resolution image.

<img id="demo" src="http://dummyimage.com/400x300" alt="Responsive Image" data-fullsrc="http://dummyimage.com/800x600">
<script>responsiveEnhance(document.getElementById('demo'), 400);</script>



Jeremy has a nice explanation on why that’s an acceptable solution (for now) (emphasis mine):

Suppose the small image is 20K and the large image is 60K. That means that desktop browsers are now loading 80K of images (instead of 60). On the face of it, this sounds like really bad news for performance… but because that extra 60K is being downloaded after the page has downloaded, the perceived performance isn’t bad at all. In fact, the experience feels quite snappy.

Agreed, it’s not good to download something twice, yet the advantages (perceived speed) currently outweigh the disadvantages (downloading an image twice + the fact that this won’t work if JS is disabled).

The Elephant

When talking about responsive web design and mobile devices, one of the key aspects that was always pushed forward was context, which has become something vague to define: it’s not because a user is visiting your site via a mobile device that he/she is “on the road”. In the same line, one can also state that:

Small screens don’t necessarily mean slow connections or mobile. Larger screens don’t necessarily mean fast connections or desktop.

And this is the elephant. All the suggested solutions I’ve seen so far only take the screen estate into account, neglecting the connection speed the device has.

To me, a proper solution would also take the connection speed into account: if a device has the space to show a bigger image, and the connection can handle it: enhance.

A Possible Solution

As there’s already a navigator.onLine property available (demo) I think it’d be fairly easy to extend navigator with a speed property. That property in its turn could then easily be mapped/expanded to become available from within media queries, or even an HTML attribute.

The suggested <picture> solution could evolve into something like this:

<picture alt="Alt tag should accurately describe the image represented by all sources, though cropping and zooming may differ.">
    <source src="mobile.jpg" /> <!-- Matches by default. -->
    <source src="high-res.jpg" media="(min-width: 800px) and (min-speed: 3G)" /> <!-- Overrides the previous source over 800px before any assets are fetched, if the the user has at least a 3G connection. -->
    <img src="mobile.jpg" /> <!-- Fallback content, in the event the <picture> tag is completely unsupported by the user's browser. -->
</picture>

The proposed 3G value for min-speed in the example will need some tweaking though. If one would have a speed with the value wifi, that could actually mean nothing: he could easily be connected via WiFi to his iPhone which is on 3G. Better solutions could be values in the likes of slowgoodfast or actual rates 100kbps10Mbps....

Does this extension look something to you? Or have we have no need to detect the connection speed of device? It’s clear that I myself think we do need it … so let’s start a discussion 😉

UPDATE #1: As Jan posted below it’s better to let the browsers handle downloading the best size, instead of putting the responsibility in the developer’s hands. If you combine this idea along with the container format (cfr. the .icns file) then there’d be no actual need for the <picture>element: just define an img set the src to the container image and the browser will cherry-pick the appropriate size based on the screen estate and the connection speed. The rules to decide which on the browser need to fetch will be tricky to define though (there will be some edge cases), but that’s a nut we can definitely crack.

UPDATE #2: Lennart Schoors (from briccs.net) hinted on Twitter that the connection speed is in some (draft of a) W3 spec. Mathias Bynens eventually pointed towards that spec, namely The Network Information API which has a Connection interface which holds a bandwidth property. As this can eventually become available, the inclusion in a media query or attribute isn’t that far away.