DM Logic

Responsive images – doing it right?

Posted on in web development

I’ve got a web project coming up where the target audience is primarily mobile users, most likely over 3G. So I decided it was time to get to grips with how to ensure the appropriate image is served based on the user device.

This article is not about media queries or responsive CSS techniques – I’m pretty comfortable with all that [** yes - I know this site looks awful on mobile! I will fix it one day**]. It’s specifically about inline images and how best to adjust the src attribute.

I’m also – at this stage – not attempting to detect bandwidth. This is all about serving an image with appropriate dimensions for the screen in use.

I started off by Googling about to see what others are doing. There seems to be quite a bit of reliance on cookies and .htaccess files going on, and I really didn’t like that. I wanted something very lean and self-contained. I also wanted something that didn’t need jQuery so it could run immediately the DOM was ready. So, as is often the way, I re-invented the wheel, and here’s how.

You can see a working demo here: http://dev.dmlogic.net/responsive/

The savings in getting the image load correct are significant, particularly for phones. For the two images on the above:

The goals of the code

HTML markup

We need a couple of things in the HEAD.

This is for some degrading which we’ll come to in a bit:

<html lang="en" class="nojs">

And this is the best option I found for IOS viewport settings

<meta name="viewport" content="initial-scale = 1, maximum-scale = 1" />

For the images themselves, here is the markup.

Morning Star

This is the most “baggy” bit of the code I’ve produced, but it can easily be automated from any decent web application. This is giving us a placeholder image with nothing in it (pixel.gif is transparent), three available src files from the data- attributes and a default of small image for non-js users.

I opted for the noscript tag rather than loading the small image first because a tablet user over 3G would not want the small image – so that would count as a needless load. pixel.gif however is tiny enough not worry and will cache when used multiple times.s

CSS

Just a couple of rules needed:

img.responsive-image { width:100%; display:block; } .nojs img.responsive-image { display:none; }

The first rule makes our images scale with a browser resize, the second ensures that the responsive images are not visible to non js browsers. Other than that just go with normal responsive best practice.

JavaScript

I’m not going to go through it line-by-line here, but here’s a summary of what happens.

The code is currently full of comments and white space, but I reckon it will compress down to < 1k with that gone. Remove the support for old browsers and it might be half that.

Known issues

Firefox refuses to shrink down to 320. Not figured out why yet.

IOS users cannot zoom the screen using a pinch. This is not ideal but the viewport settings I’ve used appear to be essential to get a different width to register on an orientation change. I’d love to solve this one.

I’ve not touched on the issue of pixel density. That is – although the iPhone 4 is reporting 320 pixels wide, there are twice that available for display. Should I be making use of them by serving a large image?

What do you think?

I’d love to hear some feedback on this. Am I missing a really good technique? Have I overcomplicated? Have I overlooked a situation where this will break? Let me know.

Comments