CSS Image Replacement for iPhone 4 High-DPI Retina Display

The new iPhone 4 is certainly a marvel of technology.  One of the surprising side effects it has is how bad it makes things look that weren’t designed for high-DPI displays.  For the most part, text is automatically beautiful on the iPhone 4 1.  However, images are a different story. What follows is my research and then the technique I used to update images on flowz.com. We use wordpress here and with this technique, image replacement is automatic. All you have to do different is upload the second, high-res file at the same time you insert the normal file in your post or page. The first thing we need to do is pull in CSS specific to high-DPI device(s) in a standards compliant way. Here is how you can do that: http://thomasmaier.me/2010/06/css-for-iphone-4-retina-display/ The trick being to use a CSS3 media query to target high DPI devices (*not* just the iPhone 4!):

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

But that is only 1/3rd the story.  How do you make sure high resolution images are used when viewing with a High-DPI display?  Aral Balkan has the answer: http://aralbalkan.com/3331 But what he illustrates only works for “sprites.”  That is, divs and other elements that use background-images where the src is specified in CSS. In that special CSS file, we specify the size of the background and include high-res background images that override the normal CSS. However, there is the problem of elements that specify their src in the HTML. I.e., img, video, etc. Aral, touches on what is required but leaves the implementation as an exercise.  I’ll dive into the details:

  1. Create double resolution copies of all your images. Name these with a suffix of “@2x”. So for logo.png, the double res would be logo@2x.png. Make sure that all of your image tags have at least a width attribute specified. (But, you are already doing that aren’t you?) If you don’t, your image dimensions will be increased to the new high-DPI source by the browser.
  2. Create a highdpi.css file.  Contents:
    .replace-2x {
    	font-size: 1px;
    }

    The sole class, .replace-2x contains an attribute that has no effect on img tags. This is the flag that will tell our javascript it is okay to do image replacement.

  3. In your source HTML, add the replace-2x class to all of your images that have a double resolution counterpart.
  4. In your HTML head, add the link for your high-dpi stylesheet:
    <link rel="stylesheet" media="only screen and (-webkit-min-device-pixel-ratio: 2)"
    	href="/css/highdpi.css"/>

  5. Create and include in your source, a highdpi.js file.  We are going to assume you are using jQuery for your site.  Contents:
    function highdpi_init() {
    	if(jQuery('.replace-2x').css('font-size') == "1px") {
    		var els = jQuery(".replace-2x").get();
    		for(var i in els) {
    			var src = els[i].src
    			src = src.replace(".png", "@2x.png");
    			els[i].src = src;
    		}
    	}
    }
    jQuery(document).ready(function() {
    	highdpi_init();
    });

The trick here is that we check to see if the font size for our special class is set to value declared in our high-DPI CSS file. (Our flag) It will only be set if the browser passed the media query. If the flag is set, grab every element in the DOM with the replace-2x class and change the src attribute to point to our high-res counterparts. If you have access to one, pull up http://flowz.com on an iPhone 4 and take a look at our logos here (zoom in if it isn’t immediately apparent to you):

Image without ".replace-2x"

Image with ".replace-2x"

(Under normal DPI monitors, the images will look identical.)

  1. Note: all text looks good, except text rendered using Cufón and sIFR. We hit that problem. A blog post will follow on that.

Sidebar

I really, really wanted to be able to do something different then what I described above. I wanted to define a class: .highdpi-supported on the body tag of all the pages that support high-dpi. I then wanted to add an uncommon attribute on that class to act as the flag to tell javascript to go ahead with image replacement. Unfortunately, I could not find any such attribute that was relatively safe *and* didn’t affect page layout. So in the end, I’m stuck with adjusting the font-size attribute on the .replace-2x class.  Maybe someone else can come up with a better flag.

About the author

Mike Wille - I'm the head techie here with a passion and hunger for all things digital. I got into programming because I love to create and couldn't cut a straight line in wood shop.

2 Responses to "CSS Image Replacement for iPhone 4 High-DPI Retina Display"

  1. Thanks for the very useful article Mike.

    I noticed that one of the snippets of code you’ve posted doesn’t work, simply due to the missing -webkit- in front of min-device-pixel-ratio within the css3 media query.

    Once I added -webkit- to this line, it all worked great.

    Thanks again.

  2. Thanks, good catch! I’ve updated the code.

Do you have something to say?

Your email is never published nor shared.
Required fields are marked *