Automatically serve retina artwork

Choosing whether to serve retina images to a website is pretty easy when using plain CSS with background images, but it gets a bit more tricky when trying to serve the images using an tag.

Sure, there are various hacks floating around the web, but they all have their own inefficiencies: For example, when using JavaScript to replace image paths, the device will likely have already started downloading the original image causing unnecessary bandwidth wastage — which can be expensive with current mobile data charges.

A better technique is to give the web server the smarts to automatically serve up retina images, when the device needs them, and when they exist on the server.

This technique requires a two part approach, and relies on a cookie being set by the web application on the first page load.


  1. The first, and most important step is to make sure you've got mod_rewrite enabled.
  2. Include this small JavaScript in the head section of your website.
    <script>document.cookie='resolution='+Math.max(screen.width,screen.height)+("devicePixelRatio" in window ? ","+devicePixelRatio : ",1")+'; path=/';</script>
  3. Finally, include this rewrite rule in your Apache config, or .htaccess file.

RewriteCond %{REQUEST_URI} ^/assets/images
#RewriteCond %{REQUEST_URI} !^/assets/images/excluded
RewriteCond %{HTTP_COOKIE} resolution=([^;,]+),2
RewriteCond %{REQUEST_URI} !@2x\.(jpe?g|gif|png)$
RewriteCond %{DOCUMENT_ROOT}/$1@2x.$2 -f
RewriteRule ([^.]+)\.(jpe?g|gif|png)$ $1@2x.$2

The first RewriteCond line tells the script that it should capture all images within should be changed to whatever path your images are stored in. E.g., if your image URL is:

Then the first RewriteCond line should be changed to;
RewriteCond %{REQUEST_URI} ^/images

You'll notice the second RewriteCond line is commented out... this line is optional, and allows you to specify a sub directory which contains images that shouldn't be included in the retina checks. Again, you'll need to change this path to suit.

The third RewriteCond tells the script to check the resolution cookie that was set when the first web page loaded. The final RewriteCond checks to see if we're already explicitly requesting a @2x artwork, so we don't append another @2x to the end of the filename.

And the final RewriteCond line checks to see if the @2x image exists on the server. If not, it will fall back on the original requested URL.


This script relies on the user having loaded a webpage with the javascript that sets the cookie. If that cookie isn't set, the user will be served the non-retina image by default.

Because of this, if you're using a different subdomain to serve images from, you'll need to make sure the cookie is set for requests on that subdomain.

You need to make sure you've put the JavaScript to set the cookie in the head section of your website — ‚preferably before you include your CSS files too. This will ensure that all subsequent HTTP requests know which artwork to send.


The main problem with this approach is that it doesn't take the users bandwidth into account. This could be an issue with mobile devices (iPhone, iPad, etc) which are using 3G connections.
If you find a nice solution to this problem, feel free to improve this technique!

Something to say?