Grow your CSS skills. Land your dream job.

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.

Comments

  1. Awesome article. Articulated exactly what I’ve found myself doing more and more of, lately. Is there anything pseudo-elements can’t do?

  2. Hott Dogg

    Awesome, thanks!

    If you need to use sprite for upper right or bottom left corners, then you can just place icons on another diagonal (from upper left to bottom right corner)

  3. Good use of pseudo elements… a few mods/additions if anyone is interested in preventing text wrapping!

    .star {
       /* ensure the icon is positioned to this element */
       position: relative; 
       /* the padding value based on the icon width + extra padding required */
       padding-left: 34px; 
    }
    .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 */
       /* Removed and replaced with position
        float: left;
        margin: 0 10px 2px 0;
       */
       position: absolute;
       left: 0; top: 0;
    }
  4. I’ve been using diagonal sprites for a while for this very reason. If you are spriting on elements that aren’t the set size of the image (such as s) you have to account for content wrapping or expanding in unintended ways.

    I came up with this technique after seeing my static templates pulled into staging sites with CMS’s with client content which would expose the traditional sprite’s limits. Until you run across that you generally don’t realize the need for better sprites.

  5. Hmm, that should have been “(such as li’s)”

  6. Dear Santa. For Christmas this year I want unlimited pseudo elements. Thanks.

    Good usage there, fight that good fight, keep that markup down.

  7. This is a really great idea, thanks for this one!

    Also diagonal sprites seems cool certain situations.

  8. Yeah I find this technique can be quite handy if you don’t want or need to use the empty span elements. I included this technique in an article on CSS background image hacks – http://nicolasgallagher.com/css-background-image-hacks/

    • Pretty lame of Chris to not credit you for the technique.

    • Yeah Nicolas was totally first. I honestly didn’t see (or at least didn’t remember if I did see) that his article contained this technique. Hey at least I wrote it up a different and original way and got the word about a bit more about this super useful technique.

  9. Yeah I use this technique quite frequently. Especially for non-critical aesthetic embellishments, which won’t break or disable the layout of they don’t appear in older browsers that don’t support pseudo-elements.

    One thing to note, though. If you’re using a clearfix method that uses the ::after element with visibility:none, you may need to override that visibility declaration, or else you won’t see the element at all. That issue drove me to the brink of insanity for a couple hours a few months back!

  10. Thierry Koblentz

    I wrote an article about something similar, with a hack for Internet Explorer:

    http://coding.smashingmagazine.com/2011/03/19/styling-elements-with-glyphs-sprites-and-pseudo-elements/

  11. John

    Does calling the background: url every time you use this effect performance?

    I thought the best part of a sprite was you only needed to call it once and use background-position on the rest?

    Thanks for any wisdom you can share on this.

  12. Hassan

    One advantage of this technique would be on RTL languages stylesheets. It’s pretty much impossible or very hard to make sprites work on RTL stylesheets. Using pseudo elements make it really easy.

  13. Charbs

    Thanks Chris!
    I just learnt the CSS Sprites method and Pseudo sprites method in 30 minutes. I can’t believe I always ignored learning about them, especially CSS sprites… Will definitely start using them.
    Charbs

  14. [rb]

    Funny… Ive always done that, figgured it was just common sense.

  15. dj

    Interesting article. Now, sprites or data uri’s … decisions, decisions :-)

  16. Seutje

    Enough of an enhancement to justify not supporting IE7 or polyfilling it!

  17. Zeeshan

    We can also use CSS Clip property to precisely locate the image we need in a sprite.

    clip: { shape | auto | inherit } ;

    Good article: http://www.ibloomstudios.com/articles/misunderstood_css_clip/

  18. Wow! Its very helpful! that what I am always facing span syntax issue with positioning of bullets or icon aligning with the text of box, you make my problem solve, because of this beautiful tricks, thanks a lot.

  19. Best post of the year!

  20. I love this? Very excellent indeed. Just remembering the extensive sprites I used to create, only way to be able to use a sprite in a scenario above was to place it in the upper left corner and use ridiculous negative position of the background.

  21. Smart use of pseduo elements, like it alot!

  22. Used my first sprite yesterday and found this article on Smashing Network.

    So glad I found this, because I wast happy using an extra meaningless span :)

    Performance AND semantics, count me in!!! ;)

  23. We changed all our sprites a while back… it helps with page speed.

  24. More for a programmer than for a designer!

  25. fcsonline

    It could be interesting to have a ‘background’ modifier like ‘no-repeat’ to cover this limitation and avoid these kind of tricks:

    Example:

    background: url(sprite.png) -24px 0 no-repeat crop;

    All the area around the cropped area, could be filled with ‘background-color’.

  26. Excellent tutorial, very well done, thanks

  27. nice Work. looking for other CSS tutorial. Thank for sharing.

  28. Permalink to comment#

    I’m having a few issues with sprites and really can’t wrap my head around some things. The tuts I’ve seen are informative and I know the background of sprites, why they’re beneficial, etc. There are a few things I’m still baffled by but the main thing is: How do the sprites replace an existing menu? All of the tuts I’ve seen create a fresh menu to the top and left (or right) of the page. I don’t see any that tweak an existing site switching out the current nav with the new sprited nav.

    Any help I’d greatly appreciate. All of you guys are speaking from an experienced perspective and this is a piece of cake for, but as a new, zealous, and ambitious designer can someone point me in a direction that’s understandable for a newbie like me. Thanks mucho!

  29. Permalink to comment#

    Forgot to mention, I am mostly always gonna use WP. How does this work with the basic layout they give you, or any for that matter? Is it different using WP for a sprited nav menu vs DW or the like?

  30. This is a fantastic technique. I love the way it works, and makes using sprites so much simpler.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".