June 23, 2010

Targeting the iPhone 4 Retina Display with CSS3 Media Queries

Four years ago, (eight months before the original iPhone was announced) Dave Hyatt wrote about high DPI web sites on the Surfin’ Safari blog:

One area of Web design that is going to become more important in the coming years is high DPI. For those of us working on WebKit, this will also become an issue for WebKit applications and for Dashboard widgets.

Zoom

The future is now.

The iPhone 4’s Retina Display doubles the pixel density we’re used to seeing on handheld devices and thus drastically improves the sharpness of text on the web. But what about images? In order to preserve the design of existing websites, images are automatically pixel-doubled. And this creates a schism between “device pixels” and “CSS pixels”.

John Gruber’s “Why 960 × 640”:

I don’t think that MobileSafari will be able to continue mapping the “px” unit to physical display pixels, because the disparity between the physical pixel size of old and new iPhones is going to be enormous.

Dave Hyatt again:

Most Web site authors have traditionally thought of a CSS pixel as a device pixel. However as we enter this new high DPI world where the entire UI may be magnified, a CSS pixel can end up being multiple pixels on screen.

For example if I set a zoom magnifcation of 2x, then 1 CSS pixel would actually be represented by a 2×2 square of device pixels.

This is exactly what’s happening on the iPhone 4.

So the question for web developers becomes, how do I update my website’s images with higher resolution versions for high DPI devices? Or better yet, how do I do all that in a way that degrades gracefully?

Apple’s Safari Web Content Guide has long recommended using CSS3 media queries to conditionally include stylesheets for specific device widths. But Hyatt’s post mentions a new feature, device-pixel-ratio, for targeting specific pixel densities.

I tried that new feature out by adding this line to my little mobile website1:

<link
    rel="stylesheet"
    type="text/css"
    href="/css/retina.css"
    media="only screen and (-webkit-min-device-pixel-ratio: 2)"
/>

This tells browsers to include “retina.css” only if the device pixel ratio is 2 or higher. (The feature seems to only be available via the -webkit extension for now.)

The “retina.css” file overrides the background images of some of my site’s graphics with higher resolution versions and uses the background-size property to set the correct CSS pixel dimensions. (I use Komodo Media’s Social Network Icon Pack and Mark James’ Silk icons for many of the graphics.)

High DPI devices represent an exciting opportunity for web developers to do some amazing things and this example only barely scratches the surface.


  1. I’ve since updated my app to include the media query CSS inline in the main stylesheet.

See also: