Responsive Images: Experimenting with Context-Aware Image Sizing

Posted by Scott on 12/14/2010

Topics:

Responsive Image illustration: contextual image sizes shown on iPhone and desktopResponsive Web Design has been a very hot topic this year, inspiring developers who long for a “one codebase serves all” future. But critics of the technique have pointed out several issues that need to be addressed before it can scale perfectly from handheld to desktop — specifically, while HTML, CSS and JavaScript can be light enough to share across all experiences, desktop-optimized images are often too heavy for mobile connections, and mobile-optimized images are too low quality for desktop viewers.

Recently, we began work on a large-scale responsive design (collaborating with the incredibly talented Mr. Ethan Marcotte, who notably got this whole "responsive" party started), in which we've set out to address this shortcoming of responsive design with a technique that requests an appropriate image size for a given context without resorting to tactics like User Agent sniffing. We feel strongly that these responsive techniques present a most practical way forward in web development. This post documents our in-progress experiment with "Responsive Images."

What is this all about?

The goal of this technique is to deliver optimized, contextual image sizes for responsive layouts that utilize dramatically different image sizes at different resolutions. Ideally, this approach will allow developers to start with mobile-optimized images in their HTML and specify a larger size to be used for users with larger screen resolutions — without requesting both image sizes, and without UA sniffing.

How's it work?

The technique consists of a few key files: rwd-images.js, rwd.gif, and some .htaccess directives. To use, just drop the .htaccess file into your root web directory (this requires an Apache web server, and if you already have an .htaccess file, you can paste its contents into your existing file), and reference rwd-images.js from an HTML page.

Any images that you'd like to scale and load responsively should start by referencing a mobile-friendly image size, adding a ".r" prefix to the file extension, and reference a larger size using a HTML5 custom attribute data-fullsrc (the image referenced by data-fullsrc will be used for screen resolutions greater than 480px).


<img src="small.r.jpg" data-fullsrc="large.jpg">

As that page loads, the rwd-images.js script inserts a BASE element into the head of your page, directing all subsequent image, script, and stylesheet requests through a fictitious directory called "/rwd-router/". As these requests reach the server, the .htaccess file determines whether the request is a responsive image or not. It redirects responsive image requests temporarily to rwd.gif (a transparent 1px gif image), while all non-responsive image requests go to their proper destination through a URL rewrite that ignores the "/rwd-router/" segment. When the HTML finishes loading, rwd-images.js removes the BASE element from the DOM (resetting the base URL) and sets the responsive image sources to either their small or large size (if specified), depending on whether the screen resolution is greater than 480px.

We've found that the technique works in most modern browsers (Safari (desktop, iPhone, iPad), Chrome, Internet Explorer (8+), Opera). The technique degrades gracefully in other browsers, such as IE7 and under. In those browsers, desktop users will still receive an appropriate image size, but the mobile image will download as well, causing slight but unfortunate overhead. As development continues, we may find a workaround to bring full support to these browsers.

Demo Page

You can view a demonstration of the technique at the following URL: http://filamentgroup.com/examples/responsive-images/

Usage Instructions, Documentation, and Ongoing Development

We're still experimenting with this technique, and we're looking for contributions and ideas. To read more about the project, or to fork the project and contribute, please check out our project on Github. While you're there, check out the issue tracker to see the problems we're currently working out.

Responsive Images on Github

Book cover: Designing with Progressive Enhancement

Enjoy our blog? You'll love our book.

For info and ordering: Visit the book site

Comments

This is great.

For further reading, see http://tinysrc.net - I’m trying to see how I can work your ideas into the way it works. More thoughts welcome!

(tinySrc uses either explicit screen-size declaration or device-specific sizing - so might be useful for those instances when you don’t have control over the images being pulled into your app or you’re also dealing with non-JS-friendly clients)

Comment by James Pearce on 12/14  at  11:27 PM

Looks great on my Droid and imac

Comment by stacey on 12/15  at  01:48 AM

This would be the perfect place for content negotiation. Anyone else think a “Vary: Resolution” header is in order?

Comment by Jason Karns on 12/15  at  09:26 AM

It would be better to have ‘progressive’ images and the browser aborts the download when it has good enough resolution of the image.

Comment by zcorpan on 12/16  at  12:44 AM

“To use, just drop the .htaccess file into your root web directory (this requires an Apache web server”

- Does this mean it is not possible with IIS?

Comment by Lorro on 12/16  at  04:10 PM

Lorro, should be possible in IIS.  All the .htaccess file does it some URL rewriting.  You would just need to translate those rules to routes or some regex based rewrite rules.

Comment by Thomas on 12/17  at  01:24 AM

Awesome Scott—I will be working this into my projects which use Responsive Design. #IOU-Beer

Comment by Eric Webster on 12/17  at  09:54 PM

Tested the demo on firefox 4 “minefield” with last build.
No “double” image download.
It seems to be working fine.

Comment by Guillaume Moulin on 12/29  at  06:29 PM

This is fantastic. Absolutely amazing work. I love responsive designs. It just makes good sense.

Comment by Joseph Rosenblatt on 01/18  at  07:06 AM

I’ve been wrestling with this problem myself for the past few weeks, which is how I came across your article. I’ve written up my attempt, would be interested to see what you think.
http://www.craig-russell.co.uk/responsive-images-and-context-aware-image-sizing/

Comment by Craig on 01/22  at  08:11 PM

I’ve just found you cited on Smashing Magazine’s article about responsive web design.
Just a question: I know that I can use custom data attributes with HTML5, but could it be feasible/easier (and useful for use with non HTML5 websites) to use your solution without “data-fullscr”?

You already rely on a rule - the “.r” prefix - for mobile-friendly images, I think you could add a second rule, adding by default another prefix when using of fullsize images is needed: “fullsize_” (or whatever else).

So in case of responsive images, you would have this code <img scr="test_image.r.jpg" > converted by your Javascript file in <img scr="test_image.jpg" > for small display and <img scr="fullsize_test_image.jpg" > for bigegr display.

Useful, I think, for using with no HTML5 - but responsive and standard compliant - webpages.

Comment by ilpiac on 02/17  at  07:06 PM

Thanks everyone.

@Lorro: You may be able to get it to work on IIS or other server setups, but the URL rewrites will need to be adapted to work in different environments. Here’s an article about converting htaccess directives to IIS: http://learn.iis.net/page.aspx/557/translate-htaccess-content-to-iis-webconfig/

@Guillaume: thanks for the heads up! Indeed, this does now work (1 request per image) in Firefox 4 :)

@Craig: we commented on your article, but in general, PHP-generated image sizes could be a fine solution. However, we do think it’s important to serve a functional image in the base markup rather than a 0px gif (so that older devices including those with JavaScript unavailable receive the content too), so we wouldn’t recommend removing the scripts and rewrites we’ve produced to facilitate that.

@ilpiac: That’s a good point. If your server is configured in a reliable way, you could do without the data-fullsrc attributes and simply redirect any images with the “r.” extension prefix to their full size image file immediately. Doing so would likely require a fixed pattern for your file naming conventions, where you can trust that an image’s full-size equivalent can be found through a consistent change in the filename (for example, police.jpg becomes police.full.jpg or even police.jpg?full). We didn’t want to impose any filename pattern constraints on users of this script, which is why we went with the data-fullsrc approach, but if you can set things up to work like that, it sounds great!

Comment by Scott (Filament) on 02/17  at  07:26 PM

Hi everyone,
I just pushed a new version of this technique that is significantly streamlined, and much improved. The new approach sets a cookie to store screen resolution, and the server immediately redirects to the appropriate image size. Also, the data-attr driven approach outlined above still works too, if you need the flexibility of data attributes (if your filenames are not consistent, predictable). Otherwise, the new script assumes a filename convention of (image.jpg vs. image.large.jpg) by default.

Also, this approach will work on any browser that has cookies and javascript available, which is likely a much broader range than the initial script. Of course, browsers without cookies or JS will just get the mobile image size, so whether it “works” is a matter of experience level rather than a general accessibility concern.

Check it out on Github and let us know how it works for you. Thanks!
https://github.com/filamentgroup/Responsive-Images/tree/cookie-driven#readme

Comment by Scott (Filament) on 04/02  at  10:10 PM

We’ve used CSS3 Media Queries to load different image sizes for different screens. Very simple: http://techblog.viewbook.com/2011/03/the-css3-media-query-for-dynamically-resizing-elements-on-your-website-for-different-screen-sizes/

Comment by Rien on 04/03  at  04:20 PM

@Rien: looks good thanks. I should clarify that this approach is about foreground images, not CSS background images, but for backgrounds we agree: media queries work well :)

Comment by Scott (Filament) on 04/03  at  06:40 PM

@Scott: Indeed that’s why we used background images. And we wanted to make sure the images did not scale themselves, but that bigger or smaller images are loaded based on screen size. Thanks!

Comment by Rien on 04/04  at  12:36 PM

Does this technique only switch the image on page load, or also do so if the browser is resized?

For instance, if I open a page on a desktop, but with the browser window very narrow, which image is loaded and does that change as I resize the window?

Comment by Philip Morton on 05/09  at  12:40 PM

How is this better than dynamically changing the path to images that need to be optimized:

Use JS to dynamically replace image path with say /images/small, /images/medium, /images/large based on screen size.

The default image is just a 1px placeholder.

No need for .htaccess or inserting/removing BASE element.

@Rien - using background is not good for content images. For example what is a desktop user wants to print and article with images?

Comment by johans on 05/10  at  10:33 PM

Ahh - found the answer to my question in your reply to Craig’s PHP approach:

“The explanation of our article doesn’t quite describe the reasoning for particular approach we took, which is providing a meaningful mobile-optimized image in the HTML, and enhancing it on larger screens without requesting both image sizes. By removing the .htaccess and the JS-generated base element from our technique, it’s impossible to serve a mobile-friendly image in the markup from the start while ensuring larger screen users do not download both image sizes (because JS alone can not prevent that first request from going out to the server). This point is critical to the approach. Simply defaulting to an empty image in the HTML means users on many feature phones (or any browser with JavaScript unavailable or disabled, and search engines as well) will receive no image at all.”

Comment by johans on 05/10  at  10:44 PM

Great idea! The folder seems unnecessary. Can’t the htaccess rewrite simply look for file calls which have “.r.” in them and manipulate those?

Comment by Kevin on 05/16  at  04:58 AM

Really nice article, only just getting onto the responsive web design band wagon and I’ve come up a jQuery & PHP solution to image resizing which works quite well:
http://www.jamesfairhurst.co.uk/posts/view/responsive_images_with_php_and_jquery/

Would love to hear what you think.

Comment by James on 05/27  at  02:25 PM

Many mobile/handheld guidelines stress including explicit WIDTH= and HEIGHT= on <IMG, so underpowered layout engines don’t have to deal with changing their layout every time an image’s real size is discovered. No “Responsive Images” solutions (including this one) I’ve seen supply the WIDTH= and HEIGHT=. Am I not fully understanding something that should be obvious? Or are the mobile/handheld guidelines I’ve seen all a bit out of date and no longer to be taken seriously? Or is this still a problem in search of a solution? Or...?

Comment by Chuck Kollars on 06/13  at  05:41 AM

Hey Chuck,
I see that advice a lot in performance guidelines too, and I’m sure it does provide a small performance gain. Unfortunately, if you’re scaling your images fluidly, the benefits of providing the width and height attrs would be lost anyway, since the browser will need to calculate its dimensions depending on its parent element when it renders the page. Also, the height attribute gets in the way of allowing an image to scale proportionally as it width increases and decreases.

It’s always game of tradeoffs, I suppose. We think the benefits of images that scale fluidly are worth it in many cases. Thanks! :)

Comment by Scott (Filament) on 06/13  at  06:24 PM

Chuck, the original justification for those guidelines (such as the W3C Mobile Best Practices) was to limit the need for the browser to reflow its layout as it was loading resources - since it can plan around the bounding box of the images as soon as the markup arrives.

With a high latency network and a slow-rendering mobile browser, the effect of the page reflowing for several seconds after the markup has rendered can be very painful and obvious.

Nevertheless, constraining width and height in markup is obviously inappropriate for sites which flow and react to screen size. Since designers are increasingly targeting better performing mobile browsers on faster networks with these techniques, some of the original best practices need no longer be so rote.

However, if you were building a site or app carefully targeted to a particular screen size (or were adapting the site on the server side, where you have a chance to influence the markup responsively too), one might continue to consider adding those attributes. Although very valid, that sort of prescription is anathema to the techniques being discussed here.

Comment by James Pearce on 06/13  at  06:53 PM

thank ypu adimin

Comment by herbalife on 06/17  at  01:56 PM

Commenting is closed for this post.

Book cover: Designing with Progressive Enhancement

Enjoy our blog? You'll love our book.

For info and ordering: Visit the book site