Regarding Sprites

Minimize server requests and create a better user experience

a tip from Luminous Works Training and Consulting

When serving images, we want to have as little delay as possible for our site's users. This is especially true for "rollover" images: those that appear when the user's cursor hovers over an element. If we use two separate images, there can be a Flash Of Unstyled Content (FOUC) before the second image loads.

So instead, we use only one image, revealing only a section of it at a time. Once the image has downloaded once, it appears instantly any other time it is required, even if it's a different part of the image we're showing. Some developers use only one sprite for entire sites!

A diagrammatic version of the image we'll use as our sprite. Note it is in eight sections. We need the height of each section as well as how far down from the top that section is (its offset). One could have horizontal offsets, too, for larger grids of "images".

To decorate an element, like the div below, we specify its width and height to match the section of the sprite we wish to see, and use the sprite as its background image. We also have to be sure to use the correct amount of vertical offset, remembering that negative values mean "up".

So, if I wanted to show only section E of the image above, I might do something like this:

the HTML:

<div class="bunny">lookee here</div>

The CSS:

div.bunny { 
	width: 318px; height: 78px;
	background-image: url(/img/spritesDemo.png); 
	background-position: 0 -147px;
	}
lookee here

For the Luminous Works site, I wanted these ornaments to occasionally appear above or below other elements to give a little something extra. I did not want to clutter my markup with extraneous DIVs. So I chose to use the CSS selectors ":before" and ":after" to include blocks with my desired ornament as their backgrounds.

<p class="prettyLineAbove">I want a pretty line above this paragraph!</p>
.prettyLineAbove { text-align: center; }
    .prettyLineAbove:before {
    	content: ""; /* that is, no textual content */
    	display: block;
        width: 318px; height: 12px;
    	background-image: url(/img/spritesDemo.png); 
    	background-position: 0 -10px;
    	margin: 0 auto .5em auto;
        }

I want a pretty line above this paragraph!

And without the diagram stuff, it really is pretty:

I want a prettier line above this paragraph!

For those of you using high-resolution displays like Apple's Retina displays, I have a double resolution version:

I want the prettiest line above this paragraph!


To generalize and make it easier on myself to apply these ornaments, I made a set of classes with easy-to-remember names: "bandabove", "bandbelow", "line2", "bunnies", etc. So if I want to have festive monkies below an H3, I'd do this:

<h3 class="bandbelow monkies">Monkies are playful and mischievous</h3>

Monkies are playful and mischievous

One class (bandabove or bandbelow) sets most of the stage: a block of the correct width above or below, with our sprite as the background image. The second class sets the height and background-position properties.


Below are the styles with the media query that detects high-resolution displays (to supply the double-resolution images). Following that is the full version of the sprite image, without all the lines and such.

.bandabove:before, .bandbelow:after {
	display: block; width: 318px;
	content: "";
	background-image: url(/img/bands.png); 
	background-repeat: no-repeat; 
	margin: .5em auto;  
	}

.line1.bandabove:before, 
.line1.bandbelow:after
			{ height: 10px; background-position: 0 0;}
			
.line2.bandabove:before, 
.line2.bandbelow:after
			{ height: 12px; background-position: 0 -10px;}
			
.thistle.bandabove:before, 
.thistle.bandbelow:after
			{ height: 71px; background-position: 0 -22px;}
			
.berries.bandabove:before, 
.berries.bandbelow:after
			{ height: 54px; background-position: 0 -93px;}
			
.bunnies.bandabove:before, 
.bunnies.bandbelow:after
			{ height: 78px; background-position: 0 -147px;}
			
.leafy.bandabove:before, 
.leafy.bandbelow:after
			{ height: 46px; background-position: 0 -225px;}
			
.monkies.bandabove:before, 
.monkies.bandbelow:after
			{ height: 77px; background-position: 0 -271px;}
			
.bugs.bandabove:before, 
.bugs.bandbelow:after
			{ height: 65px; background-position: 0 -348px;}
			
@media
only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (   min--moz-device-pixel-ratio: 2),
only screen and (     -o-min-device-pixel-ratio: 2/1),
only screen and (        min-device-pixel-ratio: 2),
only screen and (                min-resolution: 192dpi),
only screen and (                min-resolution: 2dppx)
{ 
	.bandabove:before, .bandbelow:after 
		{ 	background-image: url(/img/bands2x.png); 
			background-size: 318px auto; }
}