Don't Call Me. I'll Call You. Single Request Responsive Images

We’ve been talking about responsive design around the office a lot lately. It’s kind of a big deal these days. The holy grail seems to be responsive images, or a system that allows you to determine the correct size image for the users browser. This reduces the amount of data being downloaded by mobile devices while still providing a higher resolution version for desktop, and tablet browsers. By images I am talking about image tags, frameworks like 320 and up and media queries can take care of the layout images in css.

One of the best systems out there is by the Filament group, their code is also on GitHub. They are doing some awesome things that make it easy to get started with responsive images.

So in an effort to advance the discussion, and push this process even farther, here is a method for removing the double http request penalty associated with their system. Yep, you heard that right. 1 http request per image regardless of the size of your screen. And it’s cross browser compliant with a non-javascript fall back.

Let's take a quick look at the javascript:


var resizeImages = function(){
var imgs = $('img');
var width = $(window).width();


for(var i = 0; i < $(imgs).length; i++){
var thisImg = $(imgs)[i];
var thisSrv = $(thisImg).attr('src');
if(thisSrv == undefined || thisSrv == '')
thisSrv = $(thisImg).attr('data-src');


if(width > 1180)
$(thisImg).attr('src',thisSrv.replace(//[0-9]+//,'/1180/'));
if(width > 960 && width < 1180)
$(thisImg).attr('src',thisSrv.replace(//[0-9]+//,'/960/'));
if(width > 480 && width < 960)
$(thisImg).attr('src',thisSrv.replace(//[0-9]+//,'/480/'));
if(width < 480)
$(thisImg).attr('src',thisSrv.replace(//[0-9]+//,'/320/'));


if($(thisImg).hasClass('responsive'))
$(thisImg).removeClass('responsive');
}
};

Now that you have seen the bulk of the code we have a few things to talk about. First of all, the size cutoffs are totally arbitrary in this example. Second, this is a convention over configuration system. It requires that you have the responsive sized images stored in a strict directory structure and that you add a little bit of extra markup to handle the non-javscript fall back. But, we'll come back to that. Third, this uses jquery, though a library agnostic version would be a pretty simple derivative.

You can probably guess what the markup for an image looks like based on that function, either way here is what your markup would look like:

<img src="/respond/img/myImage.jpg" />



<img data-src="/respond/img/320/myImage.jpg" class="responsive" />
<noscript>
<img src="/respond/img/320/myImage.jpg" />
</noscript>

The first

<img>
tag is non-responsive. It will be ignored by the system and displays normally. The second, is what your tags look like for a responsive image. No src attribute. This is important, it prevents the browser from hitting the server before we figure out what image size we need. The function above handles swapping the data-src into the src and replacing the 320 with the appropriate size directory. The responsive class is critical to this whole thing too. It should default to display:hidden so that the image doesn’t appear unless javascript is running. Also prevents a flash of missing image in IE.

The last image, the one in <noscript> tags is our fallback. If the browser does not support javascript the responsive <img>, which does not contain a valid src attrribute, will not load anything and remain hidden by theresponsive class. <noscript> provides a last ditch fall back for our non-javascript users. One of the advantages to this is that it is only executed when needed, keeping http requests to a minumum. Another added bonus is you can specify what ever size image you want for the fall back. Yay freedom!

So <noscript> wrapped images are really what set this method apart. For every image you include in the page you will need to have a <noscript> wrapped version of the image immediately following, and styled similarly to, the responsive version. Is this the most elegant solution? Probably not. But for the price of a little extra code you eliminate duplicate downloads and unnecessary http requests.

One more major thing. Let’s talk about directory structure. Sorry… but it’s got to be discussed. Take a look at how the image directories are setup in the example code. There is an img directory with 4 subdirectories. Non-responsive images go in the base img directory. Appropriately sized images that will be served responsively go in each of the subdirectories. This means that you will need to provide 4 copies per image displayed on the page. Really though that’s a requirement of every responsive image solution out there.

Ok so really that wasn’t that bad was it? Here are the files and example directory structure. As always hit me up with questions or comments:Email me or tweet me.

If you enjoyed this article please share it! Also, I have a newsletter that you might enjoy as well. Thanks! -Daniel

Published: 29 Sep 2011 | Tags: frontend , markup , designs , responsive