The iPhone 4 has introduced a new challenge to web developers due to its retina display using a higher dpi than most devices. What looked sharp in desktop browsers and other lower dpi devices appears blurry and pixelated on the iPhone 4 and potentially other devices which will have higher dpi screens. The current solution is to have two sets of images one for general and one for high dpi screens. You then switch it up using media queries depending on the screens dpi, this has been documented and discussed many times. Let’s try a different approach.
So what’s different?
The difference between my solution and others is mine requires only a single sprite image and doesn’t need a special media query to keep the images looking sharp in higher dpi screens.
The above demo loads a single sprite image containing all my icons needed. This image is saved with everything double the size of what it should be.
How it works
The way I get it to display nicely for both dpi’s is to use the CSS3
background-size property to shrink it down to the correct size. Since the iPhone 4 naturally scales the image up there is no artefacts or blurriness as the image is already the correct size so you don’t need to use the special media query to make it render nicely.
If your sprite image is 192px wide then you shrink the width to 96px and set the height to auto to keep the correct aspect ratio. Setting the
background-position is also halved so if it’s 108px down you set it too -54px to get the correct offset.
See some comparison images.
iPhone 3GS on the left, iPhone 4 in the middle and Opera Mobile 11 with 291 DPI set on the right
There are drawbacks
Of course this isn’t perfect but in the correct situation is a much better solution. If you need to support older browsers or less capable then
background-size won’t work, see background-size support. There is also file size being larger since the sprite image is double the resolution the image is roughly 30-50% larger in size than the smaller counterpart if you’re working with a 8bit png.