CSS sprites are a pretty popular technique now, but I still see a lot of common mistakes or misconceptions when it comes to implementing them. Here’s a few advanced tips to keep in mind.
GIF or PNG-8 sprites should be grouped by color
If you’re taking advantage of the low file sizes offered by the GIF or PNG-8 format, make sure you’re not sacrificing any color quality at the same time.
In this example image, we have three different color groups of buttons sharing one 64-color palette (intentionally low for demonstration purposes). If you look closely you’ll see the gradients in the buttons, especially purple and orange, aren’t looking so great. Here’s just the purple group in an image of its own, using the same palette limitations:
Since the palette is devoting more of its 64 spots to the one gradient, it appears much smoother. Generally try to keep color groups in separate spritemaps, especially if the images contain gradients.
If you’re using JPEG or PNG-24 sprites, you don’t need to worry about this grouping, although you may need to be worried about file size. Managing CSS sprites is often about managing the trade-offs.
Sprites without padding break when zoomed
Certain browsers will display CSS sprites in a weird way when zoomed in or out. If the sprite has padding between each element, the browser will display the padding instead of the element next to your image.
Here’s a close-up of zoomed Chrome and zoomed Firefox (3.5.5) on At Libs, focusing on the alternating image that uses a CSS sprite (in this case, the Django pony).
In Firefox, the pony image blends in seamlessly with the surrounding image as it is designed to do (and so do the other switch-in overlays). In Chrome, however, the trick unravels as the areas around the pony image on the top and left show up when zoomed. Firefox handles this better, but it’s not necessarily a mark against Chrome, since zooming generally seems to be a crapshoot. Older versions of IE work like Firefox does here, while newer ones have the lines like Chrome. Right now, it’s best to just prepare for the lines.
To do so, just add 1px of padding between your sprites. In the fully-colored pony example, adding an additional 1px that matched the rocket background on all sides would have solved the problem. It’s a bit easier with a simple white background– just space out your sprites a bit.
Use Photoshop coordinates to quickly position backgrounds
Using a combination of rulers (View > Rulers) and the info box (Window > Info), you can easily find the top left coordinates of any image in your sprite map. Move your cursor to the right spot and the coordinates are displayed for you in Info. Use these with background-position to easily place your background. Just remember to put negative signs in front of them. If that’s confusing, then think of it as moving the background to your image, not specifying where the background itself is. Photoshop top-left coordinates of X: 15 and Y:90 would become background-position: -15px -90px;. Easy, right?
Transparent ‘spacer’ GIFs are bad
I still see this method in use now and again, and it leaves me scratching my head. After all the images on a page are loaded into a sprite map, the original img tags in the document will be replaced by a spacer image, usually a transparent 1×1 GIF. It’ll look like this:
<a href="/links"><img src="/img/spacer.gif" alt="Links" class="spriteclass" /></a>
The CSS spriting technique will then be applied to the img, with the transparent gif being stretched out invisibly. I prefer a different method which involves taking out the img tag entirely. I use this:
<a href="/links" class="spriteclass">Links</a>
Looks like a regular link, right? With some CSS we can turn it into the button we want it to be, using a technique called Fahrner Image Replacement.
.spriteclass {
display:block;
width:200px;
height:100px;
background: url('img/spritemap.png') -200px 0px;
font-size: 0;
line-height: 0;
text-indent: -9999px;
overflow: hidden;
}
The important bits here are display, font-size, line-height and text-indent. Make sure you use these values, or you’ll find your text popping up in some way in certain browsers.
With this method, you’ll find yourself relying on the img tag a lot less often, further separating your design from the semantic markup of your document. In the end, that’s a good thing. You’ll also kiss one HTTP-request goodbye when you stop using spacer.gif.
CSS Sprites shouldn’t add production time
Unfortunately most developers and designers have a bad first experience with CSS sprites. Usually a developer will learn of the technique mid- to late- in a current project. As a result, the first task he or she will be faced with is converting a site from regular old images to a full-blown CSS spritemap. Sometimes this translates to “CSS sprites are an annoying process that I have to do at the end of production.”
Well, it shouldn’t be that way. Converting a site is always tough, but designing from the ground up with CSS sprites in mind actually adds no development time. Sure, extra time is devoted to managing the sprite map and figuring out coordinates, but time is also saved by avoiding the hassles associated with multiple image files. Editing is easier. Uploading is easier. Time is also saved on markup end, with less img tags to worry about in the document itself. I’ve found that, in the end, it evens out on time, but saves on hassle.
That’s like a win/win. Or a draw/win. Either way, don’t avoid CSS sprites just because they made one project take longer.