Sprites – Cool and Refreshing

Back when I was first learning web design, you generally sliced up large images into multiple files because it was believed it resulted in a faster loading time. These days the rule is just the opposite – fewer images, JavaScript files, and CSS files can improve loading performance quite a bit. With JS and CSS, of course, you can combine and minify your JS to reduce the number of files, and thus the number of server calls. But what about those images, especially in an icon rich site?

Enter sprites! Now I fully admit, sprites is something I just kind of "oh yeah, those" for quite awhile. I had exposure to them because jQueryUI makes excellent use of them in their themes, but I didn't really look at them until today as we explored ways to optimize a slow loading page – a page with 137 table rows, each with 6 icons, plus there were 3 more icons above. I decided it was time to get off my lazy duff and look into this whole sprite thing more.

I guess the first question is figuring out just what a "sprite" is? Basically it's a single image made up of a bunch of individual images. Since it's one file and one image, it is only a single file to download to your browser and a single server request. It can save bandwidth and loading time. You then use CSS to only show the image desired where we need it to go. While they can be a bit tricky, from my understanding, for repeating backgrounds, they are ideal for things like icons! So instead of calling individual images, you might have this in your HTML for one of your icons:

<img class="home" src="img_trans.gif" />

And this in your CSS:

img.home {
width: 46px;
height: 44px;
background: url(img_navsprites.gif) 0 0;

To start, of course, we had to make our sprite image. But that required starting with optimizing our images a bit. We were doing another "old school" trick – having on image of the largest size and just resizing it on call as needed. So all of our icons were at 128×128, even though we actually never used it at any size larger than 30. So I replaced our oversized graphics with the larger ones. Now using a sprite does mean you can't resize on the fly, so for the one image we used at two different sizes, I had to make sure we had two different copies, one at each size, to go into my sprite image.

With that done, it was time to combine them…that sounds kinda of a pain, ya know? And then I have to write all the CSS to position each one? Or not. There are plenty of tools out there now to help do it for you, so it isn't nearly the aggrevation it was in the beginning! The one I ended up using came highly recommended from a few different articles on sprites, SpritePad from KISS. It was fast, easy to use, worked perfectly, and you can download the resulting image and CSS all you want. In particular, I like that it names your new classes the same as your image name – makes search/replacing SO much easier!! Oh, and its FREE! I do like that word! With the free version, you can have up to two sprites saved at a time. The paid version allows for unlimited space, team collaboration/sharing, and using an auto alignment tool.

Once I had my new sprite and the CSS, it was just a matter of going through the code and updating it to use the new sprite. In our case, instead of just throwing all of the individual sprites into a selector for the background, I made it it's own class.  So in my HTML I have something like this for our calendar icon (obviously with appropriate ALT and TITLE attributes):

<img src="/includes/images/spacer.gif" class="calendar spritedIcon" />

and this in the CSS:

.spritedIcon {
    background: url('/images/conferenceServicesIcons.png') no-repeat;
    padding: 0px !important;
} .calendar {
    background-position: -364px -215px;
    width: 32px;
    height: 32px;

It took about four hours, though it probably would have only taken two or so if we'd done it all first, then checked, versus checking while we went along. It also would have gone a little faster if we'd been more consistent with our img tag attribute ordering LOL. In the end, we went from 55 individual icons to a single tidy sprite.

Once it was all in, we just had to do a little tweaking. For example, we had some places we used padding with our icons. This didn't work with the sprite ones as it resulted in other icons "peeking" in, so we had to adjust our CSS a bit. There were also a few places I had to go clean up issues from my search/replace resulting in a double "class" attribute on my image tags. And after I had made my sprite, I stumbled on six icons that we used at a 48×48, not just our 32×32 size. Fortunately, since I used SpritePad, I just pulled up my saved sprite, added the new sizes of those images, and was good to go.

There seem to be two general schools of thoughts regarding sprites, either implementing them as you go, or doing it at the end when your site is getting its final polish. We obviously did the latter and I'm still not sure which would be easier over all. We did have some icon changes throughout the project, but updating was just a matter of updating the sprite image file and the relevant CSS – since SpritePad generated all that for me, it wasn't a huge deal. I suspect if we'd done sprites from the get go, the overhead of dealing with the icon changes would have added up to less time spent than the four hours it took to convert to it. We'll probably find out on our next project.

Meanwhile, yay to our first app that will be utilizing sprites we implemented (versus just coming with something like the jQueryUI ones).