Monday
Dec192011

Integrating CSS Sprite Creation Into a Build

CSS sprites are a standard technique for improving web performance. Combining a bunch of background images into one big image reduces the number HTTP requests. And that improvement leads to faster pages.

But CSS sprites can be hard to maintain, for instance, when it comes time to add additional images to an existing sprite. I started looking for a sprite-generation tool to integrate into our continous builds. It was harder than I expected to find such a tool. I tried css-spriter, which calculated offsets incorrectly for some images.

I finally got what I wanted by modifying David Elentok's sprites-gen.py (his github, my fork). David's tool combines several images into one sprite image. My extension generates the CSS for each image in the tool.

So, if I run python sprites-gen.py -p "http://media1.sulia.com/" sprites.png sprites.css close_grey_16.png close_orange_16.png facebook_login_button.png facebook_login_button_on.png, I'll get a combined PNG file called sprites.png and a CSS file, sprites.css, with the following contents:

.sprites_close_grey_16 {
    background: transparent url(http://media1.sulia.com/static/css/
                sprites_out/sprites.1324331505.png) 0px 0 no-repeat;
    width: 16px;
    height: 16px;
    text-indent: -5000px;
}

.sprites_close_orange_16 {
    background: transparent url(http://media1.sulia.com/static/css/
                sprites_out/sprites.1324331505.png) -16px 0 no-repeat;
    width: 16px;
    height: 16px;
    text-indent: -5000px;
}

.sprites_facebook_login_button {
    background: transparent url(http://media1.sulia.com/static/css/
                sprites_out/sprites.1324331505.png) -32px 0 no-repeat;
    width: 201px;
    height: 44px;
    text-indent: -5000px;
}

.sprites_facebook_login_button_on {
    background: transparent url(http://media1.sulia.com/static/css/
                sprites_out/sprites.1324331505.png) -233px 0 no-repeat;
    width: 201px;
    height: 44px;
    text-indent: -5000px;
}

Integrating the Generated CSS Into My Stylesheet

My newly-generated CSS is great, but the generated class names aren't meaningful. I don't want to sprinkle meaningless class names like .sprites_facebook_login_button throughout my markup. Even worse, my generated stylesheet doesn't account for hover states. The SASS CSS preprocessor helps me out with both problems.

My build generates a SASS-friendly file called sprites.scss (not sprites.css), which I import into my main SASS stylesheet:

@import "sprites.scss";

I can then define appropriate CSS classes that extend the generated classes.

.facebook_sign_in_button {
    @extend .sprites_facebook_login_button;
    &:hover {
        @extend .sprites_facebook_login_button_on;
    }
}

My markup contains simple, meaningful classes such as facebook_sign_in_button.

Next Steps

I'm excited that I can now extend and maintain my CSS sprites without rewriting my stylesheets and without running through a bunch of manual steps. But I've noticed that my handling of static files is evolving into a multi-step build process.

  1. Generate an SCSS file and a sprite PNG from my sprite image files.
  2. Generate CSS from my SCSS files.
  3. Combine and minify my CSS files.
  4. Combine and minify my Javascript.

I've got a python script that does all of the above, but I'm thinking it's time for a real build system. Stay tuned.

PrintView Printer Friendly Version

EmailEmail Article to Friend

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>
« Selenium's Sweet Spot: Preventing Catastrophes | Main | Crystal Ball: What We'll Think About "Lean Startup" In Five Years »