If you’re interested in adding retina image support to your website or app and you happen to be using SCSS, here’s a handy shortcut that makes it dead simple.

Just include this SCSS mixin in any rule and specify the high resolution image’s path and device independent pixel dimensions. Here’s an example:

div.logo {
  background: url("logo.png") no-repeat;
  @include image-2x("logo2x.png", 100px, 25px);
}

Putting the high resolution alternative in the same rule as the normal image instead of putting it in a separate @media query rule or in different stylesheet altogether is a big win in terms of clarity in our CSS. It’s easier to read, easier to understand and easier to maintain.

The image-2x mixin detects high resolution displays like this:

@mixin image-2x($image, $width, $height) {
  @media (min--moz-device-pixel-ratio: 1.3),
         (-o-min-device-pixel-ratio: 2.6/2),
         (-webkit-min-device-pixel-ratio: 1.3),
         (min-device-pixel-ratio: 1.3),
         (min-resolution: 1.3dppx) {
    /* on retina, use image that's scaled by 2 */
    background-image: url($image);
    background-size: $width $height;
  }
}

The mixin not only makes development easier, but it centralizes the definition of high resolution displays so it can easily be changed globally as more devices come to market. The @media query is based on the one in Thomas Fuchs’ Retinafy book but, for example, we’ve already modified it to define the Google Nexus 7 with it’s 1.3 pixel ratio as a retina-capable device.

A key insight here is that with SCSS, @media queries can be nested inside other rules. Such that these both work the same:

@media print {
  body {
    // print styles
  }
}

body {
  @media print {
    // print styles
  }
}

Purists of hand-crafted CSS may rail that this method results in the rule being repeated in the compiled CSS each time we use this mixin and that’s true. Basecamp is light on images so we’re talking about a handful of repetitions, not dozens or hundreds. It also seems likely that as SCSS continues to improve, these rules will be smartly combined. For now that trade-off is worth the improved clarity and convenience in our code.