CSS Icon Sprite System

At work, we make a lot of web apps. These are usually very data driven, so lots of tables and forms. To help identify actions on each page we use a number of icons for easy recognition.

We use icons in a few distinct ways. As a stand alone icon with no text and as an icon with text. The icon with text could be on it’s own, or floated left or right with other icons with text as potential actions.

As often happens in teams where many people are touching the CSS, we don’t know what all other team members have added to the site. I would find several declaration of the same icon, sometimes with the same styling but with different names such as “add-property” and then again as “add-agreement”.

So I set out to make a more efficient system for using our icons. I think this may have been around the time I first saw Nicole Sullivans Object Oriented CSS talk so I was inspired to make things a little more… object oriented (reusable chunks not tied to any given structure).

This is what I came up with.

How it works

First, lets make the element we want to act on semantically correct. Use the appropriate element (anchor, span, etc) and insert the appropriate text.

<a href="#d">Delete property</a>

Delete property

To make the site a bit more performant I wanted this system to use CSS sprites. So I combined the most commonly used icons into a diagonal sprite. Adding the class of “sprite” loads the sprite image into the layer. Since we are using a diagonal sprite that is positioned to 0,0 by default, it would show nothing. Or more specifically, the empty white space in the top left corner.

<a href="#d" class="sprite">Delete property</a>

Delete property

Not much of a change.

You then call the class of the icon within the sprite (code near end of article) that you want such as delete, edit, info, etc. This positions the sprite correctly to show the specific icon you want but it is still not spaced correctly.

<a href="#d" class="sprite delete">Delete property</a>

Delete property

Then you can add one of the following classes that define how the icon will be used (spacing). Each must be accompanied by the sprite class or they won’t work. They are as follows:

.icon

This will hide the text and show the icon only. The element will be set to the icon height (usually 16×16). Useful for a delete/edit/etc column in a table. The text is hidden, but still there for accessibility and potentially SEO if public.

<a href="#d" class="sprite delete icon">Delete property</a>

Delete property

.prefix

This will add padding to the left side of the element to make room for the icon and a little space in-between (20px total).

<a href="#d" class="sprite delete prefix">Delete property</a>

Delete property

.right

Floats the element to the right and adds a margin-left to provide spacing between multiple floated elements.

<a href="#d" class="sprite delete prefix right">Delete property</a>

Delete property

.left

Floats the element to the left and adds a margin-right to provide spacing between multiple floated elements.

<a href="#d" class="sprite delete prefix left">Delete property</a>

Hopefully it’s obvious how, by mixing the correct classes, you can create many more options then are specifically defined. You can easily add or change icons without having to go back to the CSS to create new combinations each time. You can just add a new “print” icon and instantly use it with the icon/prefix/etc classes. You don’t need to add print-icon, print-prefix, etc.

Here is the CSS

/* Set up the utility classes */
.sprite { background:url(/files/diagonalsprites/sprite-diagonal.png) no-repeat top left;}
.sprite.icon { height:16px; width:16px; overflow:hidden; display:inline-block; text-indent:100em; cursor:hand; cursor:pointer; }
*+html .sprite.icon { text-indent:0; width:0; padding-left:16px; } /*IE7 sucks*/
.sprite.prefix { padding-left:20px; height:20px; display:inline-block; }
.sprite.right { float:right; margin-left:15px; }
.sprite.left { float:left; margin-right:15px; }
/* Now the individual icons */
.accept { background-position: -234px -0px; }
.add { background-position: -208px -26px; }
.bomb { background-position: -182px -52px; }
.delete { background-position: -156px -78px; }
.feed { background-position: -130px -104px; }
.heart { background-position: -104px -130px; }
.lock { background-position: -78px -156px; }
.pencil { background-position: -52px -182px; }
.star { background-position: -26px -208px; }
.user { background-position: -0px -234px; }

Conclusion

I hope this system, or a derivative of it, can help you in your work. Several on my team have found this to be a great time saver. Once you understand the system and can remember the names of the specific icons, you can easily create many different displays for your icons without ever having to go back to the CSS. I use this almost daily at work and love the simplicity it bring to my pages.

I would love any feedback on how it can be improved and to hear of how you leverage it your own projects.

10 thoughts on “CSS Icon Sprite System

  1. I think this is very helpful for productivity, but I can be a little against the separation of structure and design philosophy, don’t you think? what if one link with the class “icon left”, should go to the right and have no icon on a future redesign?

  2. @fs – You are correct. This system doesn’t match the CSS philosophy of all coders. For our use at work these things basically never change. An icon in a table row for editing or deleting will pretty much never change to a prefix as we want to conserve the column width. An icon for “Add new ___” at the top or bottom of the table will similarly rarely change to just an icon as we want the text for context.

    The system likely won’t work for everyone. It has worked well for us and I haven’t had a single issue with needing to change it so far. YMMV.

  3. Hello there, You’ve done a fantastic job. I’ll certainly digg it and personally suggest to my friends. I’m confident they will be benefited from this web site.

  4. Aaron! Thank you! Used this today to set up the small social icons section on a company footer I put together. You can view it here >> http://flourishtorque.com/projects/playmark/index.html

    It’ll all go live by next week. I had to tweak a few things here and there. For some reason, I had the entire link set with a thin dotted line (1px dotted white), but it would only stretch the width of the icon and not the entire link. Had to ditch it the line.

    I’m sure it’s one line of code someplace.

    Loved it, thank you. Rock on.

    BE, Seattle

    • There isn’t really an easy way to do that because the x/y system is top/left based, and you can’t switch to a “from the right” number.

      The only way you can do it is by using a sprite that is vertically stacked (as opposed to horizontal or diagonal) and use the “right” keyword to align it to the right. But then you can’t position it very well if you wanted to adjust it by a few pixels.

  5. Have you ever considered about adding a little bit more than just your articles?

    I mean, what you say is valuable and all. However think about if you
    added some great visuals or videos to give your posts more, “pop”!
    Your content is excellent but with images and videos, this website could certainly be one
    of the greatest in its field. Wonderful blog!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>