CSS Sprites


Simply put, a sprite, when used in your Cascading Style Sheet, is one image containing multiple images. The idea behind using a sprite is to lesson the amount of HTTP Requests your webpage makes to the server, and also try to limit the amount of data being downloaded from the server. If done correctly, this can greatly increase your website’s load times. You see it more often on bigger websites, such as Youtube. Bigger sites that have an intense amount of traffic need to limit the amount of requests made to their web servers. Big site or small, though, you should use sprites in your CSS whenever possible.

If you take a look at Youtube, you will notice that just about the entire site is in one sprite. This works because their site design is minimal enough to support it all on one. It’s likely that you will have more design aspects and will need more images, and so in that case you should use multiple sprites, and whenever possible. They are very common among content-tabs, or with any boxy design where you need rounded corners. They are also utilized very well when you need to provide multiple themes for a given design. One sprite can contain all the icons for a given theme, and so when the site operator wants to switch themes, the code just needs to load a new image. If every themed sprite has the same elements positioned in the same place, all of the CSS stays the same and you have a new look on your site. Their most common usage, though, is probably for rollover images.

When creating a sprite, each image has its own placement, with a small amount of space (if any) between it and the next image. Sprites work with the background-position CSS rule. This rule allows you to move the background so it displays at certain positions in your element. Since each image in your sprite is at a specific location, when you want to display a particular image, you position the background so the top left corner of the image aligns with the top left corner of your HTML element. Then the width and height of your element need to match the width and height of the image you are displaying.

Let’s take the following image for a quick example. It has 5 stars in it, each with a slightly different color. Each star occupies exactly 19 pixels in width by 20 pixels in height. Using CSS classes, we can display a different color star in various places on our site, and we only have to download one image. Let’s take a look.

Stars Sprite Image

With CSS, we create a class labeled ‘star’ and assign the stars image you see above as the background image. We specify the width and height of a single star, and then we make classes for each star color. The different color CSS classes will need to reposition the background image so the appropriate star displays as it should.

.star {
	background-image:url(small_stars.png);
	width:19px;
	height:20px;
}
 
.star.lightblue {
	background-position:0px 0px;
}
 
.star.red {
	background-position:77px 0px;
}
 
.star.darkblue {
	background-position:57px 0px;
}
 
.star.green {
	background-position:38px 0px;
}
 
.star.yellow {
	background-position:19px 0px;
}

Now, we use the classes together in order to style a star with a specific color: <div class=”star green”></div> for instance, will give us a green star. This also demonstrates how CSS rules can be cascaded, or used together.

Light Blue Red Dark Blue Green Yellow

Navigation Tabs With Sprites

Since sprites can be used for various purposes, I’ve also chosen to demonstrate its usage with a more complex example: navigation tabs. Let’s pretend we are making an HTML navigation, and the designs need to have ‘tabs’ for each link, and each tab has rounded left and right corners. The first thing we need to do is create an image with our tab designs on them. We can call this image ‘navtop.png’. Tabs are a little tricky because the content on the tab may be long or short, so we need to account for this. We do this by making the tab image extremely long, so that no matter the text size, we don’t run out of image. Things become clear when you look at the sprite below. We also need to account for rollover and active states. When a user puts their mouse over a tab, we want the colors to change, and if the user clicks on a tab, when the next page loads, it should load the tab in an active-state. The active state should have different colors than the rollover and non-active states. The colors change because the images are being switched. To account for this, we will have all the images in the same sprite.

This technique is otherwise known as ‘sliding windows’, or ‘sprited sliding doors’.

First thing’s first, we need to create the sprite image. I’ve created mine, so hopefully after looking at it, you will understand how you need to create yours. For this exercise, it’s easy, just three really long tab images, one for the non-active state, one for the rollover-state, and one for the active state.

Navigation Tabs

Now we need to put it together. Let’s create our navigation with an unordered list. Make sure to give your UL a unique ID attribute, so we can refer to it when styling. If you want to use the same sprite for tabs in multiple areas on your site, you can use a class name instead of an ID attribute.

<ul id="topnav">
	<li><a href="link_one.html">Link One</a></li>
	<li><a href="link_two.html">Link Two</a></li>
	<li><a href="link_three.html">Link Three Has a Longer Name</a></li>
	<li><a href="link_four.html">Link Four</a></li>
</ul>

Next we need to style our navigation menu so that each LI item is next to the other, with some space in between them. We use a right or left margin to give them space, whichever fits best into your design. In order to get them to display on the same line and next to each other, we need to float each LI element ‘left’. We also need to give each LI a fixed height. This is the height of our tab images, but not the entire sprite, just one image. My tabs are 29 pixels tall. LI elements come pre-styled, each with a bullet point, so we’re going to have to strip those styles as well. Let’s take a look at the CSS code needed to accomplish this.

#topnav li {
	/* get rid of default styles */
	list-style-type:none;
	list-style-position:inside;
 
	/* float left so they line up next to each other */
	float:left;
 
	/* set a fixed height */
	height:29px;
 
	/* give each LI a right margin */
	margin-right:15px;
}

And so what used to look like this:

Ends up looking like this:

It’s always a good rule to start with * { margin:0; padding:0; } at the top of your css layout, that way you don’t have unexpected spacing. The browsers like to put their own margins and spacing on specific elements and it can throw you off when laying out a design. In this rule, * refers to every element, so you’re saying, every element has no margin and no padding. This way, you can assign margins and paddings wherever you need them.

It’s time to style the tabs. Tabs can be tricky to style because both corners need to show a rounded edge, and the content may be long or short, so the tab image that is displayed is not a fixed width. In order to make this work, we have to use the background image on two different tags. One tag will have the background image aligned to the left, so the left corners show, and the other will have its background image aligned to the right so that the right corners show. The tag with the text inside it should have the right positioned background, and it should be nested within the first tag. An example of this nested relationship can be found above, where we have an LI tag, with an anchor tag nested inside of it: <li><a href=”my_link.html”>My Link Text</a></li>. The LI tag will have it’s background positioned left, and the anchor will have its background positioned right. The anchor tags also need to be displayed as block-elements so that they contain the entire ‘body’ of their parents. The background image for both tags should be positioned at its top most position, since that is where our non-active state is positioned in the sprite.

My tabs look better with a black background, so I am going to nest them within a parent container. My parent container is just a DIV with background-color set to black. I also like to start my tabs a little from the left, so I’m going to give my parent container a left padding.

Now, because of our rounded corners, we need to give a little room for the design, so that the content doesn’t flow into the corners. For my corners, I will set aside 9px from the left of the tab, and 9px from the right of the tab. We can accomplish this using padding. Let’s look at the CSS:

/* here are the styles for our new container element */
#topnav_container {
	width:100%;
	height:29px;
	background-color:#000;
	padding-left:50px;
	padding-top:50px;
}
 
#topnav li {
	/* these are old rules explained above */
	list-style-type:none;
	list-style-position:inside;
 
	float:left;
 
	height:29px;
	margin-right:15px;
 
	/* here is our left padding, it goes on the LI */
	padding-left:9px;
 
	/* this is our new background rule */
	background:url(navtop.png) top left;
}
 
/* this is our new rule for anchor tags */
#topnav li a {
	/* disply as a block element */
	display:block;
 
	/* here is our right padding, it goes on the anchor */
	padding-right:9px;
 
	/* anchors need a fixed height, too, which is the height of the LI minus any top or bottom padding */
	height:29px;
 
	/* this is the background style for our anchors */
	background:url(navtop.png) top right;
}

And this is what we end up with:

As I’m sure you noticed, the link colors don’t blend nicely with our tab images, and the placement is way too high. In your document, you will also have to adjust the font-size, because unless previously set, the font size for your links will be the default font size. Mine are pre-styled with my theme, and so they look smaller on this step than they normally would. You will have to adjust the font-size and the top padding of your anchor tags. Just remember that when you adjust the top or bottom padding, you need to subtract those amounts from the height. I’m going to give my links a top padding of, 8px, which means I will make the height 21px instead of 29px. I’m also going to style my links so they are readable, which means I’ll give them a different color and I will strip away the underline.

#topnav li a {
	/* old rules, explained above */
	display:block;
 
	padding-right:9px;
 
	background:url(navtop.png) top right;
 
	/* new rules for positioning, font size and color */
	padding-top:8px;
	font-size:14px;
	color:#cfcfcf;
 
	/* get rid of the underline */
	text-decoration:none;
 
	/* because of our new top padding, the height changes */
	height:21px;
}

And this is the new result:

Now it’s time to incorporate the rollover and active states of our tabs. What we need to do is get the background image to re-position itself whenever the mouse goes over the LI. This is accomplished with the :hover and background-position CSS rules. The background-position rule lets you position your background in different ways. We are going to position our background image with pixels. The rule works like this, background-position:left-pixel-position top-pixel-position; If you specify 0px for both values, it targets the top left corner. If you give a value greater than 0px, it targets the oposite corner. The left pixel position is from right to left, 1px being the right most position in the image. The top pixel position goes from bottom to top, 1px being the bottom most position in the image. Since our tabs are 29px in height, if we say, background-position:0px 29px; we will be styling the last tab in the sprite, which happens to be our active-state. We need to add styles for our active state and our rollover-state. Remember, though, that our anchor tag background images are positioned to the right, and our LI background images to the left. Let’s take a look at the new CSS for these rules:

/* style the active state - the active's rollover state doesn't change, so use the same rule */
#topnav li.active , #topnav li.active:hover {
	background-position:0px 29px;
}
 
/* style for the active state's anchor tag - the rollover state doesn't change, so use the same rule */
#topnav li.active a , #topnav li.active:hover a {
	color:#000;
	background-position:right 29px;
}
 
/* when the mouse is over the LI, change it to the rollover-state */
#topnav li:hover {
	background-position:0px 58px;
}
 
/* when the mouse is over the LI, change the anchor's image to the rollover state and change the font color */
#topnav li:hover a {
	color:#FFF;
	background-position:right 58px;
}

And here is the final result. I’ve made one of my tabs active, so you can see what it looks like. To make it active, give the LI the class=”active” attribute.

View: Live Example

VN:F [1.9.22_1171]
Rating: 7.8/10 (49 votes cast)
VN:F [1.9.22_1171]
Rating: +7 (from 9 votes)
CSS Sprites, 7.8 out of 10 based on 49 ratings
Share/Save

, ,

  1. #1 by Viper on September 30, 2010 - 1:37 am

    Another very nice guide, i will give this a try in my project im working on now, and bug you if i cant get it right

    VA:F [1.9.22_1171]
    Rating: 4.0/5 (6 votes cast)
    VA:F [1.9.22_1171]
    Rating: +2 (from 2 votes)
(will not be published)