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;
}
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:
- 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.
- 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.
Awesome article. Articulated exactly what I’ve found myself doing more and more of, lately. Is there anything pseudo-elements can’t do?
Work in IE<8
Be animated by CSS transitions in Webkit.
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)
Good use of pseudo elements… a few mods/additions if anyone is interested in preventing text wrapping!
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.
Hey Bainton! Small world…
Hmm, that should have been “(such as li’s)”
https://css-tricks.com/9189-browser-support-pseudo-elements/
Dear Santa. For Christmas this year I want unlimited pseudo elements. Thanks.
Good usage there, fight that good fight, keep that markup down.
This is a really great idea, thanks for this one!
Also diagonal sprites seems cool certain situations.
A really nice example.
One thing to have in mind – don’t go crazy on the amount of icons you have in your diagonal sprite. All sprite images have the memory problem due to wasted white space, but in diagonal sprites it’s squared.
In the example the icons are 24×24, so the resulting (uncompressed) sprite will be 24*24*n*n px. Assuming each px is 4 bytes (RGBa – although I didn’t do the testing myself [1]) 20 icons may cost you almost a Mb of RAM. 40 icons will cost you almost 4 Mb of RAM. Add 10 more icons and you may effectively kill iPhone’s Safari [2]
NB: I’m not advocating against sprites. I’m just saying don’t go crazy with diagonal ones ;)
[1] http://blog.vlad1.com/2009/06/22/to-sprite-or-not-to-sprite/
[2] http://cubiq.org/testing-memory-usage-on-mobile-safari
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.
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!
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/
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.
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.
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
Funny… Ive always done that, figgured it was just common sense.
Interesting article. Now, sprites or data uri’s … decisions, decisions :-)
Enough of an enhancement to justify not supporting IE7 or polyfilling it!
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/
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.
Best post of the year!
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.
Smart use of pseduo elements, like it alot!
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!!! ;)
We changed all our sprites a while back… it helps with page speed.
More for a programmer than for a designer!
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’.
Excellent tutorial, very well done, thanks
nice Work. looking for other CSS tutorial. Thank for sharing.
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!
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?
This is a fantastic technique. I love the way it works, and makes using sprites so much simpler.