Get an eyeful of this

How to serve hi-res images to retina displays

Here’s a to-scale comparison between a standard image shown on Apple.com, and the retina-ready image delivered when visited by an iPad.

With high-pixel-density “retina displays” the hot new thing in town (thanks to the new iPad MacBook Pro), web designers are busy upgrading their sites for these super-sharp screens. Since these devices have twice as many pixels packed into the same space, images will need to be twice as large.

But higher-resolution images mean increasingly large file sizes, potentially eating up masses of bandwidth. Thankfully, several great tools have already sprung up to only deliver high-res images to high-res screens - here’s a round-up.

 

Your bread and butter: CSS media queries

With the rise of responsive design, media queries are quickly becoming an everyday tool for web designers. But did you know that media queries can be tailored not only to the width of the screen, but also its pixel density?

You can use these features to detect high-density screens and switch background images to higher-resolution versions, or increase font size to increase text readability.

Unfortunately, as with most exciting new features there isn’t yet a standard syntax for these resolution media queries (Ben Frain has a great round-up of the methods for each browser). At the moment, the W3C are heading towards using min-resolution as as cross-browser standard, where dppx is “dots per pixel”:

@media (min-resolution: 1dppx) {
    /* Your styles here */

}

Standard devices tend to be 1dppx, and high-resolution screens like Apple’s “retina” devices tend to be 2dppx (Wikipedia has a useful list of devices - look for the “CSS pixel ratio” column). Unfortunately, we can’t yet rely on this option since it isn’t supported in most browsers. 

If you only care about targeting Apple products you can settle for using -webkit-min-device-pixel-ratio:

@media (-webkit-min-device-pixel-ratio: 1) {
    /* Your styles here */
}

We don’t recommend that, though, since retina-resolution screens are likely to become more common as other manufacturers follow Apple’s lead. Until the W3C makes a decision - and the browser vendors get around to implementing it - Ben Frain recommends using the following full vendor stack to cover all bases:

@media (min-resolution: 192dpi), (-webkit-min-device-pixel-ratio: 2), (min--moz-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 2/1), (min-device-pixel-ratio: 2), (min-resolution: 2dppx) {
    /* Your styles here */
}

Note that dpi is the dppx multiplied by 96, while the -o-min-device-pixel-ratio is just the dppx followed by /2. This may be a messy solution, but it’s an unfortunate reality in today’s world. @idiot puts it best:

The major problem with relying on media queries exclusively is that it only allows control of background images, and not <img> tags. Thankfully, developers have come up with a few scripts for getting around this issue.

 

Adaptive <img>s option 1: retina.js

Retina.js is an open-source script by Imulus which, when visited by a retina device, goes through your code and swaps out images for high-resolution equivalents if they’re available. It works similarly to Apple’s own solution for serving up images for its retina devices.

All you need to do is download retina.js, stick it on your server and call it just before the closing </body> tag.  For each image, you should have two copies: a standard-resolution one with any name (for example, “cat-picture.jpg”) and one with @2x appended (in this case, “cat-picture@2x.jpg”).

Retina.js also comes with a LESS CSS mixin to do the same to background images in your CSS, essentially automating the CSS media queries mentioned above (albeit only with support for Webkit browsers).

 

Adaptive <img>s option 2: Picturefill

Another script worth taking a look at is picturefill by Scott Jehl. This works a little differently, giving a wider range of options depending on the browser and allowing screen width to be accounted for in addition to resolution.

Jehl has modelled his script on the HTML5 <video> tag, with several source files for different cases. Here’s an example of the relevant code (there’s also a live demo):

  <div data-picture data-alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia">
       <div data-src="small.jpg"></div>
       <div data-src="medium.jpg" data-media="(min-width: 400px)"></div>
       <div data-src="large.jpg" data-media="(min-width: 800px)"></div>
       <div data-src="extralarge.jpg" data-media="(min-width: 1000px)"></div>

       <!-- Fallback content for non-JS browsers. Same img src as the initial, unqualified source element. -->
       <noscript><img src="external/imgs/small.jpg" alt="A giant stone face at The Bayon temple in Angkor Thom, Cambodia"></noscript>
   </div>

As you may have noticed, this method also relies on media queries, and so will need Ben Frain’s rather messy code from above to ensure cross-browser support.

 

Scalable vector icons using icon fonts

The above options work well for detailed bitmap images, but flat icons are most at risk of looking blurry on high-dpi screens due to their sharp edges. One option is to use icon fonts - which, being vectors, can scale to any size. Modern pictograms is a great example, easily embedded using @font-face and providing a range of fairly standard icons.

 

The future of <img>s: the <picture> element

The W3C’s Responsive Images Community Group are currently mulling over the best permanent solution for dealing with responsive images. Their current proposition (which is far from set in stone, and won’t work in any browser yet) is:

<picture>
   <source srcset="small-1.jpg 1x, small-2.jpg 2x">
   <source media="(min-width: 18em)" srcset="med-1.jpg 1x, med-2.jpg 2x">
   <source media="(min-width: 45em)" srcset="large-1.jpg 1x, large-2.jpg 2x">
   <img src="small-1.jpg">
</picture>

If you’ve noticed that it looks a lot like the markup for Picturefill, you’d be correct - and unfortunately, it has the same disadvantage of relying on media queries.

The inconvenient truth is that, until all browsers support the same standardised media query for screen resolution, we’re going to have to use Frain’s messy cross-browser stack.


If you enjoyed this, why not subscribe to webdev360 on Twitter, Facebook or Google+?

Elliot Bentley

What do you think?

JAX Magazine - 2014 - 03 Exclucively for iPad users JAX Magazine on Android

Comments

Latest opinions