Now that the New iPad is out, and there have been various clues that perhaps future Apple screens on other devices will have a similar resolution, handling high resolution images has become an important issue for many designers.
Below I'm going to outline four different ways to replace your images. I'm using PHP and jQuery for the example code as this is a good baseline for most developers. The logic of each is the key part, so porting ideas to other languages shouldn't pose much of a problem.
There are two types of image - ones included via an img element, and CSS background images. For ones using img, you need to specify the width and height, then provide an image that has double the size for each dimension. For CSS background images you need to use the CSS3 property background-size to scale the image correctly. This can be done simply using media queries - something like:
#image { background: url(image.png); } @media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (-moz-min-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2/1), only screen and (min-device-pixel-ratio: 2) { #image { background: url(image@2x.png); background-size: 50%; } }
In the way that Apple are doing this, I'm assuming that any image you want to be high res has a copy with @2x added before the file extension. To see what I mean, check out the images from the Apple site: Normal and Hi Resolution.
OK, so this isn't the best way, but it's very easy. Simply replace:
<img src="image.jpg" alt="" width="200" height="100" />
with
<img src="image@2x.jpg" alt="" width="200" height="100" />Pros
Rather nicely, there is a property exposed by the browser called devicePixelRatio. This tells us what's going on. On retina devices, it's got the value of 2.
This means that we can just insert our images like normal, like this:
<img src="image.jpg" alt="" width="200" height="100" />
Then we can use jQuery like this:
// Set pixelRatio to 1 if the browser doesn't offer it up. var pixelRatio = !!window.devicePixelRatio ? window.devicePixelRatio : 1; // Rather than waiting for document ready, where the images // have already loaded, we'll jump in as soon as possible. $(window).on("load", function() { if (pixelRatio > 1) { $('img').each(function() { // Very naive replacement that assumes no dots in file names. $(this).attr('src', $(this).attr('src').replace(".","@2x.")); }); } });
If desired, you could add a class onto the images you want to be replaced, and only replace those by modifiying the selector.
ProsApple make use of a head request for every image before they try to replace it - this seems rather wasteful though. A better way might be to write a PHP script that returns a list of all the @2x images, then only replaces them if they are in the list.
Write some php like this,
<? function is_in_string($haystack, $needle) { if (strpos($haystack, $needle) !== false) { return 1; } else { return 0; } } function get_dir_contents($web_directory) { $directory = $_SERVER['DOCUMENT_ROOT'].$web_directory; if(file_exists($directory)) { $myDirectory = opendir($directory); while($entryName = readdir($myDirectory)) { if (is_in_string($entryName, "@2x")){ $dirArray[] = $entryName; } } return $dirArray; } } header('Content-type: application/json'); echo json_encode(get_dir_contents("/my/image/directory")); ?>
Then just check if the new image source is in that json before replacing. That script will return something like:
["image1@2x.jpg","image2@2x.png","image3@2x.jpeg"]
So, if we update our JS to be this:
// Set pixelRatio to 1 if the browser doesn't offer it up. var pixelRatio = !!window.devicePixelRatio ? window.devicePixelRatio : 1; $(window).on("load", function() { if (pixelRatio > 1) { $.getJSON('/that/php_file.php', function(data) { $('img').each(function(){ var $$ = $(this); // check it's not an external link if ($$.attr('src').lastIndexOf("http://", 0) !== 0) { var imgIndex = data.indexOf($$.attr('src')); // is the image in the JSON? if (imgIndex >= 0) { $$.attr('src', data[imgIndex].replace(".","@2x.")); } } }); }); } });Pros
After some investigation, it seems that technique 3 combines the best of everything, and is the one to use! How are you approaching this? Do you have a better technique?
Comments/Questions?
Please add any questions/corrections/extra info below. Please be courteous to other users.
blog comments powered by Disqus