Displaying Retina-Quality Images
Apple has retina image display wrong -- and I think I can do better.
With the fresh release of the iPad, iPhone, and other high-resolution displays into the market, there is renewed discussion in the web development community about how best to create responsive websites with retina-quality images. The way Apple.com has decided to tackle this problem has been well-documented by Jason Grigsby and others. Unfortunately, I think they're doing it in a way that is not only inefficient, but also sets a horrible example for the web development community.
The Problem
Higher quality displays are coming; Apple's iPad and iPhone retina displays are only the beginning. So, the web development community has to start thinking about the best way to serve up images that are designed for these devices.
The big problem here is the lack of a standard detection method at the server level. Currently, there's no easy way to know the display resolution of a device until it can execute some client-side code. That's why Apple.com has chosen to serve up "standard" images (HTTP request #1), then use Javascript to replace those images with higher-quality images (HTTP request #2). But, not before also making sure the high-quality image exists on the server (HTTP request #3). That's 3 HTTP calls for every image! It's also serving up 2 full images for each image displayed. That's insanity.
So, how can it be better? How can we serve up the correct image the first time, if the browser doesn't know what to request from the server? How can we make sure we're not wasting bandwidth on throwaway images? All in a way that allows for backwards compatibility and is reusable as a standard practice for any website?
Solution Overview
Before I get into the details of how my technique works, I want to offer an executive summary right off the bat. This solution requires both a client-side component (Javascript) and a server-side component (My example is in ColdFusion. You can use any language you prefer). It will make only 1 HTTP call. It will work for new & old browsers alike. Most importantly, it will serve up retina-quality images to devices which can handle them and standard quality images to whose which can't. No wasted bandwidth.
Sound good? Still interested? Read on.
Pages: 1 2
Great idea Rob – I like the thinking behind it.
However, I’d be a little concerned about having all my images (especially some larger, retina-quality ones) being served through ColdFusion. You’re essentially taking something which is what your web server is designed to handle really efficiently – serving static files to the browser – and routing it through ColdFusion, putting much more load on the CF server.
My method (which I haven’t tried out yet, but I think it should work!) would be to start with the same cookie being placed on the client, but then to use URL rewriting (.htaccess, etc) to switch between images.
Rewriting can both detect cookies and check for a file’s existence, so you could achieve exactly the same functionality, but without the added overhead on the CF server.
When I have the time I might test this out, and if it works I’ll report back and/or write a blog post about it…
@Seb – That’s a valid concern. I did some performance tests on the CF code in this post and it was taking from 0-1ms to complete. So, I’m not too concerned about the performance of the script itself.
I will say, however, that there are certain inherit limitations with this approach. First and foremost, it relies on cookies. That means we’re limited to serving images from the same domain only because of browser security limits (Same-Origin Policy). Some people would lose the ability to leverage a CDN like Amazon S3 or other 3rd party. All things to consider, and the same would hold true for your approach — which I really like as well.
The one thing the use of a CF/PHP/Rails/etc. solution allows is extra flexibility in scripting logic. For a simple filename swap, I would love to see your approach in action. However, when I originally created the concept for this approach, I was also thinking about dynamic image servers (like Adobe Scene7), which generate images on the fly based on URL params. In that case, I would like to say “Multiply current size by X, so it fits this pixel ratio,” etc. Do a little math and…magic!
I’m totally open to other solutions, or variations on this concept. My only goal is to push the conversation in the right direction.