Adaptive Images for Responsive Designs
Adaptive Images for Responsive Designs
So you’ve been building some responsive designs and you’ve been working through your checklist of things to do:
- You started with the content and designed around it, with mobile in mind first.
- You’ve gone liquid and there’s nary a px value in sight; % is your weapon of choice now.
- You’ve baked in a few media queries to adapt your layout and tweak your design at different window widths.
- You’ve made your images scale to the container width using the Fluid Image technique.
You’ve done a good job so pat yourself on the back. But there’s still a problem, and it’s as tricky as it is important: image resolutions.
HTML has an <img> problem
CSS is great at adapting a website design for different window sizes - it allows you not only to tweak layout but also to send re-scaled versions of the design’s images. And you want to do that because a mobile phone does not need a 1900px background image after all .
HTML is less great. In the same way that you don’t want CSS background images being larger than required, you don’t want that happening with <img>’s either. A mobile phone only needs a small image but desktop users need a large one. Unfortunately <img>’s can’t adapt like CSS, so what do we do?
Well, you could just use a high resolution image and the Fluid Image technique would scale it down to fit the viewport: but that’s sending an image five or six times the file size that’s really needed. Which makes it slow to download and unpleasent to use. Mobiles are pretty impressive devices - my ancient iPhone 3G is more powerful in every way than my first proper computer - but they’re still terribly slow in comparison to today’s desktop machines. Sending a massive image means it has to be manipulated in memory and re-drawn as you scroll. You’ll find phones rapidly run out of RAM and slow to a crawl.
Well OK, you went mobile first with everything else so why not put in mobile resolution <img>’s too? Well because even though mobile device’s are rapidly gaining share in your analytics stats they’re still not likely to be the major share of your user base. I don’t think desktop users would be happy with pokey little mobile resolution images, do you? What we need are Adaptive Images.
Adaptive Image techniques
There are a number of possible solutions, they all come with pro’s and con’s, and it’s not as simple to find a graceful solution as you might expect.
There’s a detailed round-up of potential techniques for solving the Adaptive Images problem over at http://www.cloudfour.com/responsive-imgs-part-2/ if you fancy a dig around exploring all the options currently available. But I’m here to show you what I think is the most flexible and easy to implement solution, so here we are.
So, what does this solution do?
- It allows <img>’s to adapt to the same break-points you use in your Media Queries, giving granular control in the same way you get with your CSS.
- It installs on your server in five minutes or less and after that is automatic and you don’t need to do anything.
- It generates it’s own re-scaled images on the server and doesn’t require mark-up changes; so you can apply it to existing web content.
- If you wish, it will make all of your images go mobile-first (just in case that’s what you want if JS/Cookies aren’t available).
Sound good? I hope so. Here’s what you do:
Setting up and rolling out
I need to assume you’ve got some basic server knowledge along with that wealth of front-end wisdom exploding out of your head: that you know not to over-write any existing .htaccess file for example, and how to set file permissions on your server. Feeling up to it? Excellent:
- Download the latest version of Adaptive Images either from the website or from the GitHub repository.
- Upload the included
adaptive-images.phpfiles into the root folder of your website.
- Create a directory called
ai-cacheand make sure the server can write to it (CHMOD 755 should do it).
That’s it, unless you want to tweak the default settings. You likely do, but essentially you’re already up and running.
How it works
Adaptive Images does a number of things depending on the scenario the script has to handle but here’s a basic overview of what it’s doing when you load a page running Adaptive Images:
- A session cookie is written with the value of the visitor’s screen size in pixels.
- The HTML encounters an <img> tag and sends a request to the server for that image. It also sends the cookie, because that’s how browsers work.
- Apache sits on the server and receives the request for the image. Apache then has a look in the
.htaccessfile to see if there are any special instructions for files in the requested URL.
- There are! The .htaccess says “Hey server, any request you get for a JPG, GIF, or PNG file just send to the adaptive-images.php file instead.”
- The PHP file then does some intelligent thinking which can cover a number of scenario’s but I’ll illustrate one path that can happen:
- The PHP file looks for the cookie and finds out that the user has a maximum screen size of 480px.
- The PHP has a look at the available Media Query sizes that were configured and decides which one matches the users device.
- It then has a look inside the /ai-cache/480/ folder to see if a rescaled image already exists there.
- We’ll pretend it doesn’t - the PHP then goes to the actual requested URI and finds that the original file does exist.
- It has a look to see how wide that image is. If it’s already smaller than the user’s screen width it sends it along and stops there. But, let’s pretend it’s 1000px wide:
- The PHP then resizes the image and saves it into the /ai-cache/480 folder ready for the next time someone needs it.
It also does a few other things when needs arise, for example:
- It sends images with a cache header that tells proxies not to cache the image whilst telling browsers they should. This avoids problems with proxy servers and network caching systems grabbing the wrong image and storing it.
- It handles cases where there isn’t a cookie set, and you can choose whether to then send the mobile version or the largest configured Media Query size.
- It compares time-stamps between the source image and the generated cache image - to ensure that if the source image gets updated, the old cached file won’t be sent.
There are a few options you can customise if you don’t like the default values. By looking in the PHP’s configuration section at the top of the file you can:
- Set the resolution breakpoints to match your Media Query breakpoints
- Change the name and location of the ai-cache folder
- Change the quality any generated JPG images are saved at
- Have it perform a subtle sharpen on re-scaled images to help keep detail
- Toggle whether you want it to compare the files in the cache folder with the source ones or not
- Set how long the browser should cache the images for
- Switch between a mobile first or desktop first approach when a cookie wasn’t found
More importantly, you probably want to omit a few folders from the AI behaviour. You don’t need or want it re-sizing the images you’re using in your CSS for example. That’s fine - just open up the
.htaccess file and follow the instructions to list any directories you want AI to ignore. Or, if you’re a dab hand at re-write rules you can remove the exclamation mark at the start of the rule and it’ll only apply AI behaviour to a given list of folders.
As I mentioned, I think this is one of the most flexible, future-proof, retro-fittable, and easy to use solutions available today. But, there are problems with this approach as there are with all of the one’s I’ve seen so far. In the case of Adaptive Images they are these:
This is a PHP solution.
I wish I was smarter and knew some fancy modern languages the cool kids discuss at parties, but I don’t. So, you need PHP on your server. That said, Adaptive Images is Creative Commons and I would welcome anyone contributing a port of the code. 
Content Delivery Networks.
Adaptive Images relies on the server being able to intercept requests for images, do some logic, and then send one of a given number of responses. Content Delivery Networks are generally dumb-caches, and they won’t allow that to happen. Adaptive Images will not work if you’re using a CDN to deliver your website.
A minor but interesting Cookie setting issue.
$mobile_firsttoggle allows you to choose what to send a browser if a cookie isn’t set. If FALSE then it will send the highest configured resolution, if TRUE it will send the lowest.
- Even if set to TRUE, Adaptive Images checks the User Agent String. If it discovers the user is on a desktop environment it will over-ride $mobile_first and set it to FALSE.
This means that if
$mobile_first is set to TRUE and the user was unlucky (their browser didn’t write the cookie fast enough) mobile devices will be supplied the smallest image, and desktop devices will get the largest.
For today Adaptive Images is a pretty good solution. It works, and as it doesn’t interfere with your mark-up or source material in any way, the process is “non-destructive”. If a future solution is superior you can just remove the Adaptive Images files and you’re good to go - you’d never know AI had been there.
However this isn’t really a long-term solution in the grand scheme of things, not least because of the intermittent problem of the cookie/image-request race condition. What we really need are a number of standardised ways to handle this in the future.
Firstly we could do with browsers sending far more information about the user’s environment along with each http request (the device size, the connection speed, the pixel density, etc) because the way things work now is no longer fit for purpose. The web now is a much broader entity used on far more diverse devices than when these technologies were dreamed up, and we absolutely require the server have better knowledge about device capabilities than is currently possible. Relying on cookies to do this job is not cutting it, and the User Agent String is a complete mess no longer fit for the varying purposes we are forced to hijack it for.
Secondly, we need a W3C backed mark-up level solution for when we need to supply semantically different content at different resolutions, not just re-scaled versions of the same content, as Adaptive Images does.
I hope you’ve found this interesting and will find Adaptive Images useful.
- While I’m talking about stopping mobile phones from downloading resources they don’t need; You should be careful of your media query construction if you want to avoid Webkit downloading all the images in all of the CSS files. [back to reference]
- There currently exists a ColdFusion port of an older version of Adaptive Images at https://github.com/cfjedimaster/Adaptive-Images. I do not have anything to do with ported versions of Adaptive Images. [back to reference]
- Adaptive Images has a very broad Creative Commons license and I warmly welcome feedback and community contributions via the GitHub repository.