A reasonable way to show high resolution images on retina displays

Thijs van der Vossen

Since the release of the New iPad, there have been quite a few scripts to help you show high resolution images on your website when it’s being viewed on a retina display. Even though these scripts might seem like a quick and simple solution, they almost always slow down both the loading and rendering of your page.

I’ve even seen one that find all the image elements on your page, takes the image URLs from the src attributes, adds “@2x” to the filenames, performs XMLHttpRequests for each of these new filenames to see if there’s a retina version of the image on the server, and then replaces the value of the src attribute with the new URL for each request that doesn’t result in a 404.

Granted, that’s pretty nifty. It also results in three HTTP requests instead of one for every single image on your page. That obviously takes time and costs bandwidth. On top of that, the browser will have to first load jQuery as well as the script and build the DOM before it can even start thinking about getting your high resolution images (normally, the browser starts loading images in parallel immediately when it comes across one in you HTML source).

Below I’ll give two methods I use to show high resolution images on retina displays. The first is for photos and illustrations, the second is for when you want 1:1 pixel mapping for user interface images.

Use higher resolution images everywhere

In most cases, it’s perfectly fine to use a single high resolution image regardless of the resolution at which it’s viewed. Just set the size you want the image to be displayed at with CSS or the width and height attribute.

Suppose you want to show a photo at 300×200. Normally, you’d resize it down to 300×200, save it as JPEG, and include it with:

<img src="photo.jpg" alt="A sunset">

To get retina support, resize it down to 600×400 and include it with:

<img src="photo.jpg" alt="A sunset" width="300">

Done.

The added benefit is that even on a regular display you’ll be able to reveal more detail by zooming in. Prints will also look sharper.

The downside is obviously a larger file size. In my experience, this is much less of a problem than you might expect. Because of the way JPEG compression works, doubling the resolution doesn’t mean you’ll also double the file size. On a retina display you can get away with much stronger JPEG compression because artifacts are much less noticeable. You also won’t see these compression artifacts on a regular density display because they’ll be smoothed out as a result of the downscaling.

Just use your eyes to tweak the JPEG compression level when saving, and use a tool like ImageOptim to strip any metadata that’s not needed.

Please note that older versions of Internet Explorer use a crappy image resampling technique by default. Add the following to your CSS and it will also use high-quality bicubic resampling:

img
{
  -ms-interpolation-mode: bicubic;
}

Use media queries for interface images

With user interface images, you often want 1:1 pixel mapping. In that case you’d use a media query that checks for the device pixel ratio.

#toolbar a,
button
{
  background: url(images/sprite.png);
  background-size: 500px 250px;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  #toolbar a,
  button
  {
    background: url(images/sprite2x.png);
  }
}

You can save yourself a lot of typing by using a single rule with multiple selectors to define the sprite image. Because we’ve set the background-size, you can use the same background-position offsets with both the regular and the retina resolution sprite image.