Simple CSS retina sprite with Sass and Compass 

Create sprites fast for both normal and retina screens

Adrian Florescu
Front-end WTF

--

TLDR

Intro

Recently I had to create a UI that contained tons of icons and since this is a project that will have to go down to IE8 and up to the finest Retina display, the two options I had were: Font Icons or CSS sprites.

I love font icons, I used them a bunch of times, but I don’t really like how the implementation goes and to update any icon font is a hard task if you don’t use a service like icomoon.

Setup

For this to work we need to have installed SASS and Compass. I use either prepros or codekit for my setup, but you can install sass on your machine manually too.

Add the PNG images in the two formats (small and 2x). The 2x version on the icon must be exactly 2 times bigger or else the icons or elements will be shifted on the retina screen.

Export

If you have the icons or elements in PSD format, you can use a batch process to make the icons 2x or use a paid app like slicy but I don’t think it’s worth the money.

In my example, I used the PSD from entypo and used the slice tool to slice any icons I needed from there. Export the icons in the normal icons folder and then, in the PSD, you can go to image -> image size, select percentage and add 200% (the slices will be automatically resized too) and now you can export the icons in the retina folder.

Once you have all the PNG in two separated folders — my naming convention is normal & retina, add these two in your images folder under another folder called, let’s say “icons” ☺

SASS & Compass Setup

I recommend to add this CSS file as a separate task in SCSS and as a separate CSS file because if you have many icons, the compilation process can take a while (few seconds).

I created a ui-elements.scss file that will be exported as ui-elemets.css, where we need to import compass and add the following:

@import ‘compass’;@mixin bp-retina {
@media
only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and ( min—moz-device-pixel-ratio: 2),
only screen and ( -o-min-device-pixel-ratio: 2/1),
only screen and ( min-device-pixel-ratio: 2),
only screen and ( min-resolution: 192dpi),
only screen and ( min-resolution: 2dppx) {
@content;
}
}
$naviconsNormal: sprite-map(“icons/normal/*.png”, $spacing: 10px);
$naviconsRetina: sprite-map(“icons/retina/*.png”, $spacing: 20px);
.icn{
background: $naviconsNormal;
display: inline-block; // or block
@include bp-retina {
background: $naviconsRetina;
//Instead of sprite-path might be sprite-url
@include background-size(image-width(sprite-path($naviconsNormal)) image-height(sprite-path($naviconsNormal)));
}
}
@each $i in sprite_names($naviconsNormal){
.icn-#{$i}{
background-position: sprite-position($naviconsNormal, $i);
@include sprite-dimensions($naviconsNormal, $i);
}
}
@include bp-retina {
@each $i in sprite_names($naviconsNormal){
.icn-#{$i}{
$ypos: round(nth(sprite-position($naviconsRetina, $i), 2) / 2);
background-position: 0 $ypos;
}
}
}

Find the gist here: https://gist.github.com/adyz/9774898. You can help update this.

When you compile, compass will generate two sprite images and the CSS for this.

To read more about Compass sprites please read: http://thesassway.com/intermediate/spriting-with-sass-and-compass. My script does that and also generates the retina sprites with help from the retina media query and background size property that compass sends.

The output for all this will be:

.icn {
background: url(‘/images/icons/normal-s568a198c74.png’);
display: inline-block;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min—moz-device-pixel-ratio: 2), only screen and (-o-min-device-pixel-ratio: 2 / 1), only screen and (min-device-pixel-ratio: 2), only screen and (min-resolution: 192dpi), only screen and (min-resolution: 2dppx) {

.icn {
background: url(‘/images/icons/retina-sbd0775314e.png’);
-moz-background-size: 24px 319px;
-o-background-size: 24px 319px;
-webkit-background-size: 24px 319px;
background-size: 24px 319px;
}
}

This means that you will load the retina sprite only if you have a retina display. After the code above, it’s all regular stuff.

.icn-camera {
background-position: 0 0;
height: 20px;
width: 22px;
}
.icn-checkmark {
background-position: 0 -30px;
height: 18px;
width: 19px;
}
.icn-dislike {
background-position: 0 -58px;
height: 22px;
width: 22px;
}
.icn-heart {
background-position: 0 -90px;
height: 20px;
width: 20px;
}

HTML

Any icon that you want to add in the HTML has to have two class names icn and icn-{name}.

<span class=”icn icn-like”></span>

Create Style Guide

With some great help from this video you can discover that having auto maintained style guide it’s very easy with SASS:

$i: 0;
@each $icon, $content in sprite_names($naviconsNormal) {
$i: $i + 1;
.styleguide .icons li:nth-child(#{$i}) {
&:before {
content: ‘’;
@extend .icn;
@extend .icn-#{$icon};
display: inline-block;}
&:after {
content: ‘icon-#{$icon}’;
padding-left:10px;
display: inlin-block;
}
}
}

HTML:

<div class=”styleguide”>
<ul class=”icons”>
<li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li><li></li> <!--Add unlimited number of list items-->
</ul>
</div>

This will generate:

Generated icons in the browser

This my first post ever so please be nice.

--

--