Sunday, August 28, 2011

Spriting with Compass

I use little icons in various places on EatDifferent, like to show food bonuses in the stream:

The browser can take a while to load lots of images since it has to make a request for each one, so I decided to implement icon spriting - baking all the images into one image, and using background-position in CSS to make what appears like a standalone icon.

Thankfully, I was already using SASS and Compass for my CSS, and it comes with built in spriting.

After putting my icons in one folder (and sizing them all to be 16*16 pixels), I added this to the top of my .scss file:

    @import "icon/*.png";
    @include all-icon-sprites;

I also specified sizing and display properties for the special "icon-sprite" class in my .scss file:

    .icon-sprite {
      width: 16px;
      height: 16px;
      display: inline-block;
      margin-right: 2px;
    }

Compass then auto-generated CSS rules for my icons - one rule to specify the background for each of them, and a rule per icon to specify the background-position. It also applies any of the ".icon-sprite" rules it found to all of the generated icon classes. Here's a snippet of the auto-generated rules:

    .icon-sprite, .icon-activity, .icon-android, .icon-bodylog, .icon-buddies, .icon-camera, .icon-comment, .icon-edit, .icon-female, .icon-foodlog, .icon-grassfedmeat, .icon-highfive, .icon-home, .icon-homecooked, .icon-localfood, .icon-logs, .icon-organicveg, .icon-profile, .icon-reminder, .icon-settings, .icon-settings2, .icon-stats, .icon-stats2, .icon-sustseafood, .icon-tip {
      background: url('/img/icon-s97f5308db7.png') no-repeat;
    }

    .icon-activity {
      background-position: 0 0;
    }

    .icon-android {
      background-position: 0 -27px;
    }

    /* line 99, ../sass/_common.scss */
    .icon-sprite, .icon-activity, .icon-android, .icon-bodylog, .icon-buddies, .icon-camera, .icon-comment, .icon-edit, .icon-female, .icon-foodlog, .icon-grassfedmeat, .icon-highfive, .icon-home, .icon-homecooked, .icon-localfood, .icon-logs, .icon-organicveg, .icon-profile, .icon-reminder, .icon-settings, .icon-settings2, .icon-stats, .icon-stats2, .icon-sustseafood, .icon-tip {
      width: 16px;
      height: 16px;
      display: inline-block;
      margin-right: 2px;
    }

I measured the loading performance of my site before and after spriting, using the HAR Viewer, and these are the results:

Before: 28 requests 2.61s (onload: 1.92s, DOMContentLoaded: 1.64s)
After: 15 requests 1.09s (onload: 817ms, DOMContentLoaded: 600ms)

As you can see, spriting had a significant effect on performance. I definitely recommend spriting (and Compass) for sites that display multiple images on page load.

No comments: