March 9, 2012 12

Compass/SASS Mixins for Simple Retina Images on Websites


Retina Display

The iPhone 4 and 4S have had high resolution retina screens for a while but now that the new iPad has been announced with an incredible 2047×1536 resolution retina images are going to be increasingly important for web sites and web apps.

I’ve created a small extension for Compass/SASS that makes using retina images much easier to manage.Firstly, its probably worth noting that the ideal solution for web images moving forward is going to be vector based. As screen screen resolutions get higher, so will the size of bitmap images. I still however think we’re a couple of years away from being able to wholesale switch to vector images, so in the mean time here is some code that will help make your life easier.

You can download the code and read the docs on how to install from GitHub.

What does it do?

For anyone who has used XCode to create an iOS app will know, images prefixed with a @2x will be used as a replacement for standard artwork when run on a retina display. As an example, if you had an icon named icon-home.png you could simple add icon-home@2x.png to your project and the later image would be used on retina screens instead.

The important thing is to make sure that the @2x images are twice the dimensions of the normal image.

This is a very simple solution and I wanted something similar for web apps I was working on. So I wrote a couple of custom Ruby functions and a couple of mixins and now a similar workflow can be achieved using Compass.

Using the extension you would call the following mixin:

.icon {
    @include background-image-retina('icon-html.png');

This would first output the following CSS:

.icon {
    background-image: 'image_dir/icon-html.png';

And then if an @2x was found it would also output:

@media only screen and (-webkit-min-device-pixel-ratio: 2)
    .icon {
        background-size: 50% auto;
        background-image: 'image_dir/icon-html@2x.png';

If no @2x image is found, the retina CSS isn’t included but the Compass runtime won’t throw an error.

I’ve also included another helper function, which does the same but creates inline data URI’s instead:

@include inline-background-image-retina('icon-html.png');

I hope this is useful to a few others, I’d love to hear any feedback or feel free to raise a pull request if you find bugs or make improvements.

  • Matija Marohnić

    I’m confused… Won’t this resize the background to cover only half of the width of the container (concerning width)?

  • Joe Lambert

    This has the desired effect if you’re explicitly setting the size of the container to be the size of the original image.

    I’ve modified the code in GitHub to use the size of the original image in the background-size rule rather than just 50%. This should make the mixins a little more robust and usable in more situations.

    Thanks for the feedback.

  • Matija Marohnić

    Oh, I get it. Nice idea :)

  • Kaelig

    Great job, I will definitely use it in my future projects.

  • Anthony Short

    You should make this a rubygem so we can install it easily :)

  • Joe Lambert

    I’m pretty new to Ruby so not familiar with how to do this, feel free to package it up for a release :)

  • Leevi Graham

    I can’t verify this because I don’t have an Ipad3 but I don’t think the extra rules will be needed.

    According to this post: images are being auto rendered by mobile safari without any extra code.

    The following image in the page src: also has a _2x version:

  • Joe Lambert

    I saw an article about this yesterday but assumed that this was custom JavaScript code Apple was deploying on to achieve this affect. Do you think this is a browser level “feature” then?

    My guess is this is a specialised JS thing Apple is deploying on just their own site as I don’t think its the most bandwidth efficient of solutions for generic use (e.g. iPad3′s have to download low res and high res images).

  • Anthony Short

    I might just do that. It will only take a couple of minutes

  • Anthony Short

    Seems that they’re doing it with data attributes and this script 

    The CSS version could prevent both being downloaded if you used a second media query for the first image with a pixel density of 1

  • Joe Lambert

    Good point, I don’t think that would degrade too well for browsers that don’t support Media Queries though?

  • dasphere

    Was a gem ever created for this? If so, where can I find it?