Responsive images using cookies

via Responsive images using cookies | Keith Clark.

A while ago now, Keith Clark tweeted about using cookies as a means of serving images to a browser based on the size of the device viewport. Scott Jehl has already implemented the idea into a branch of his responsive images script but now that I have a platform to document my ideas I’ve decided to write up my approach to responsive images.

CSS media queries allow us to develop flexible designs that adapt to the device rendering them. Initially designers worked in a “desktop-down” fashion designing for large screen sizes, working down to the smallest. This approach has since been challenged and now projects such as Mobile Boilerplate and ‘320 and Up ‘ are encouraging a “mobile-up” approach to design.

When it comes to imagery it doesn’t matter which way you choose to implement responsive design because you’ll always end up with the same problem; the dimensions of the images used in a page will always be dictated by the largest screen resolution you designed for.

This becomes an issue as a design scales down to fit smaller screens. The high resolution image is still downloaded by the browser before it’s scaled down to fit into a smaller space. Not only is this a waste of bandwidth, downloading oversized images can also significantly delay the initial page render time. These issues are compounded if the visitor is browsing over a mobile network.

We need a way to serve a scaled version of an image based on the dimensions of the device viewport. There have been a few approaches to this issue, most of which require JavaScript to dynamically modify the src attribute of <img> tags based on the window size of the browser. I have a different approach to solving this problem.

Enter cookies…

Whenever a browser requests a file from a server it automatically forwards any cookie data along with the request. If we use JavaScript to populate a cookie with the current screen dimensions all subsequent requests made by the browser will pass this data to the server. In other words, the server would know the screen size of the device asking for the file.

Setting the cookie is easy. A single line of JavaScript will do the trick, but it must be added to the page <head> to ensure the cookie is set before any images are requested from the server.

document.cookie = "device_dimensions=" + screen.width + "x" + screen.height;

I’m storing the dimensions of the screen rather than the browser window so the server can determine the maximum size an image could be rendered at. I can’t reliably use the dimensions of the browser window because it could start out at relatively small size causing low-res images to be downloaded on a hi-res screen and these images would look terrible if the browser was later increased in size.

Working with the cookie on the server

Now the server is able to detect the dimensions of the requesting device we need a script to act on this information and send back an optimised image. For this example I’m using PHP, the code we need is listed below:

 <?php $device_width = 0; $device_height = 0; $file = $_SERVER['QUERY_STRING']; if (file_exists($file)) { // Read the device viewport dimensions if (isset($_COOKIE['device_dimensions'])) { $dimensions = explode('x', $_COOKIE['device_dimensions']); if (count($dimensions)==2) { $device_width = intval($dimensions[0]); $device_height = intval($dimensions[1]); } } if ($device_width > 0) { $fileext = pathinfo($file, PATHINFO_EXTENSION); // Low resolution image if ($device_width <= 800) { $output_file = substr_replace($file, '-low', -strlen($fileext)-1, 0); } // Medium resolution image else if ($device_width <= 1024) { $output_file = substr_replace($file, '-med', -strlen($fileext)-1, 0); } // check the file exists if (isset($output_file) && file_exists($output_file)) { $file = $output_file; } } // return the file; readfile($file); } ?> 

In my website’s ‘images’ folder I created ‘index.php’ and populated it with this code. I also added my high resolution image ‘test.png’ along with two smaller versions named ‘test-med.png’ and ‘test-low.png’, these we will be sent to smaller screens.

And finally we need an html document:

<!doctype html> <html> <head> <title>Responsive Images Test</title> <meta charset="utf-8"> <script> document.cookie = "device_dimensions=" + screen.width + "x" + screen.height; </script> </head> <body> <img src="images/?test.png"> <!-- the above is equivalent to: <img src="images/index.php?test.png"> --> </body> </html> 

How it works

The html page contains the JavaScript to set the cookie and a <img> element. The image points to the ‘index.php’ script, using the query string (the part after the ‘?’) to specify the file name of the required image. The cookie will be set before the image is requested so the screen dimensions of the device will also be passed to the php script.

The php script itself is pretty simple. It checks for the existence of the cookie and sets the $device_width and $device_height variables accordingly. If the cookie isn’t set these variables would evaluate to zero causing the script to return the high resolution version of the image. If $device_width is not zero, the script then determines which image would be appropriate for the screen and, if it exists, returns it to the browser.

I purposely named the php script ‘index.php’ so I can omit it’s name from file references. I also added it to the images folder so I can toggle progressive and non-progressive images by adding / removing the ‘?’

What if cookies or JavaScript are disabled?

If JavaScript or cookies are disabled then the device dimensions cookie will never be set, which means the high-resolution version of the file will be downloaded as a fallback. Nothing breaks, and we’re no worse off than we were before using this technique.

Are there any caveats?

Yes, but only one. Any images will need to be hosted on a cookie enabled domain.

Summary

This technique isn’t limited to <img> elements. It could be used to serve responsive images to your CSS. In fact, it can be used for much more than serving images – any file requested from the server could, in theory, be responsive.

We could improve this technique further by appending window.devicePixelRatio to the cookie the php script can detect for HD and Retina displays and serve higher resolution graphics. The php script could also be adapted to automatically scale down images for us.

Advertisements

10 comments on “Responsive images using cookies

  1. Wow, incredible blog layout! How long have you been blogging for? you made blogging look easy. The overall look of your website is fantastic, let alone the content!

  2. Hey there! This is my first comment here so I just wanted to give a quick shout out and tell you I really enjoy reading your articles. Can you suggest any other blogs/websites/forums that cover the same subjects? Thanks!

  3. I’m not sure exactly why but this site is loading very slow for me. Is anyone else having this issue or is it a problem on my end? I’ll check back later on and see if the problem still exists.

  4. I was wondering if you ever considered changing the layout of your site? Its very well written; I love what youve got to say. But maybe you could a little more in the way of content so people could connect with it better. Youve got an awful lot of text for only having one or 2 images. Maybe you could space it out better?

Comments are closed.