Pseudo Spriting

Published by Chris Coyier

You know about CSS Sprites right? They are fantastic to use when you know both the height and the width of they element you are applying them to, because then you can make a really tightly compact sprite image and use very exact coordinates to display exactly the bit you want to.

Sprites are also very usable when you know either the width or height of the element. When that's the case you line up all your sprites in that known direction. Say you know the width - you can reference them by their X coordinate and width, but not worry about an unknown/changeable height accidentally revealing other images.

When sprites "fail" is when you want to use them on an element where you can't know the width or height. Think of a paragraph (<p></p>) element. You may have a fluid layout so you can't count on width1 and paragraphs can have any number of words so you can't count on height. But you still wish you could use an image from your sprite on it.

In this scenario, what you need is an element in which you can impose a width/height/both within that paragraph to apply the sprite to. You might think:

<p>
   <span class="star"></span>
   Lorem ipsum...
</p>

Then we could use the span to apply the star.

.star {
   /* Size of star within sprite */
   width: 24px;
   height: 24px;

   /* Sprite */
   background: url(sprite.png) -24px 0 no-repeat;
   
   /* Position/Spacing */
  float: left; 
  margin: 0 10px 2px 0; 
}

But this star we are trying to apply is purely aesthetic and thus it would be best to avoid dedicated markup for it. Let's ditch it and use a pseudo element instead! Pseudo elements are the perfect answer when you need an element to work with on the page but don't want additional markup.

Let's put the class name on the paragraph (probably more semantic anyway):

<p class="star">
   Lorem ipsum...
</p>

And use a CSS pseudo element (:before) to add an element with a known width and height in which to apply the image:

.star:before {
   /* Empty content, but required for pseudo element to display */
   content: "";
   
   /* Size of star within sprite */
   width: 24px;
   height: 24px;

   /* Sprite */
   background: url(sprite.png) -24px 0 no-repeat;
   
   /* Position/Spacing */
  float: left; 
  margin: 0 10px 2px 0; 
}

View Demo

Another way?

Another possible way to handle the unknown height/width scenario is to arrange sprites diagonally (a technique I first saw from Aaron Barker). This way you can sort of slice out a single sprite even when the parent element has unknown width and height:

This is clever, but it has some rather significant drawbacks:

  1. The dimensions (and likely file size) of the sprite is guaranteed to be larger than sprites in a single row, or better, smooshed into a compact square.
  2. The diagonal shown above will work if you want to position the image in the upper left or bottom right, but not upper right or bottom left (or anywhere else).

The pseudo element method has neither of these drawbacks.

Related

Great minds think alike. Rick Harris has a similar article: Sprites and CSS Pseudo Elements.


1 Even if you could count on the width of a paragraph, spacing your sprites out as wide as a paragraph is impractical and against the core idea of sprites: efficiency.