Pixel Envy

Written by Nick Heer.

Proposed Browser Support for Retina-Ready Images

Scott Gilbertson writes for Wired‘s Webmonkey blog:

The WebKit project recently added experimental support for the proposed CSS level 4 image-set specification. Image-set is designed to offer web developers a way to target high-resolution screens, solving one of the design challenges of Apple’s Retina displays.

Both Safari 6 and Chrome 21 support image-set with vendor-prefixes and developer Jason Grigsby has put together a test page over at Cloud Four, where you can see the new image-set in action.

Quick interpolation: you read that right—incredibly, there are already CSS4 draft proposals, even though CSS3 is barely final.

It’s a really cool solution, but to explain why it’s so great, we need to back up to the current way of targeting high-res displays. Let’s use my stylesheet as an example. If you view this site on a regular display, the following CSS will be loaded to draw the Pixel Envy logo:

#logo a{
        display: block;
        float: left;
        background: url('images/logo.png') 0px 0px;
        width: 223px;
        height: 61px;
        text-decoration: none;
        margin-left: -80px;
    }

This is the 1x code. If you visit this site on a high-res display, like that of an iPhone 41, the following additional CSS will be loaded:

@media (-webkit-min-device-pixel-ratio:2) {
#logo a{
        background: url('images/logo@2x.png') 0px 0px no-repeat;
        background-size: 221px 123px;
    }
}

The first line of that snippet is a media query. It looks for WebKit browsers which are reporting that they’re running on a device with a pixel ratio of 2:1—that is, any retina display. The additional rules for the logo override the background image that was already loaded.

You’ll note that there’s a required declaration of background size. This is because browsers running on a retina display automatically double the pixel measurements of every element. But since I’ve already doubled the size of the background image to compensate, it’s doubling it again. To compensate, the background image needs to be drawn at the 1x virtual pixel size, which makes it 2x-sized. Makes sense? Great.

According to this draft specification, I could avoid using that media query and additional CSS by writing it like this:

#logo a{
        display: block;
        float: left;
        background-image: url(images/logo.png);
        background-image: -webkit-image-set(url(images/logo.png) 1x, url(images/logo@2x.png) 2x);
        width: 223px;
        height: 61px;
        text-decoration: none;
        margin-left: -80px;
    }

Very clean, and very elegant.

There’s an even smarter component to this. Astute readers will note that retina displays are most popular on mobile devices right now. If they want to accommodate those beautiful displays, web designers have to send higher-resolution (and therefore larger-sized) images over mobile connections. It’s a small paradox with the current state of web design.

This specification is very smart, however, because mobile browsers could identify when they’re on a slow connection and automatically switch to the 1x image size. Then, when the user is back on a fast connection, the browser could intelligently switch back to the 2x images. This is helpful for web designers because there isn’t a way to target specific internet connection speeds, in the same way that we can target browser sizes or pixel ratios.

There’s a test page up at Cloud Four if you want to see this in action. It requires Safari 6 or Chrome 20+.


  1. And you should, by the way, because I just added some responsive features which are pretty great, if I do say so myself. ↩︎