Optimizing with Image Sprites and CSS for Beginners (Part 2)

Optimizing with Image Sprites and CSS for Beginners (Part 2)

I know what a sprite is, now what?

In Part 1 of Optimizing with Image Sprites and CSS for Beginners I went through an explanation of what sprites are, how they work, and why to even bother. This time around we’re going to jump into some implementation of these sprites. I am still calling this Beginner stuff (only so that I can hit everyone with some hardcore code in the future), but if you happen to get confused follow me on Twitter and ask away!

What am I going to use the sprite for?

First let’s figure out what we’re even going to use the sprite for. When you’re ready to start slicing up your design, use your intuition and think of the graphical elements which will be used and reused on your site; this usually includes your navigation and maybe some buttons. In this example I’m going to use a sprite to create a “close” button and a textual navigation bar (SEO FTW). Here’s what I’ll be working with:

sprites

Let’s open with a close

This is the close button which I want sprite-ized:

Close

Your processes may be different, but I always start off with the HTML markup. The reason is because I want it as clean as possible and easily accessible for our search crawler friends. With a few quick keystrokes and a little touch of magic, this is what my markup for the close button looks like:

<a href="/close" title="Close this badboy" id="close">Close</a>

That was easy! Now let’s fancy this up with a bit of CSS magic and add the graphical close icon:

a#close {
	display: block;
	height: 14px;
	line-height: 14px;
	font: 11px 'Verdana','Arial',sans-serif;
	padding-left: 20px;
	background: url(sprites.gif) -32px -100px no-repeat;
}
a#close:hover {
	background-position: -32px -114px;
}
a#close:active {
	background-position: -32px -128px;
}

Wait.. what?

I skipped about 20 steps there, so let’s go through this line by line:

	display: block;

We need to give our link element layout so the graphic doesn’t get cropped. Display as block, kablammo problem solved! Almost..

	height: 14px;

The close button consists of a 14×14 area on our sprite map. We need to set the height so we don’t get any cropping.

	line-height: 14px;
	font: 11px 'Verdana','Arial',sans-serif;

This part is a bit arbitrary. I set the line-height just so the text is vertically positioned evenly, and the font is a tribute to Ikea (don’t hurt me :) ).

	padding-left: 20px;
	background: url(sprites.gif) -32px -100px no-repeat;

The fun part! The padding is there so that the text for “close” is shifted to the right and not disturbing the space for the graphic. But where the hell did I get the -32px -100px from? It’s the sprite’s position! 32 pixels from the left, and 100 pixels from the top. An easy way of finding your graphic positions in your sprite map is to open up the file in Photoshop, use the rectangular marquee tool (M), then start a selection from the top left of the document and end at the topmost and leftmost of the graphic. Check your Info window (F8) and take note of the width and height of your selection– and there are your positioning coordinates!

a#close:hover {
	background-position: -32px -114px;
}
a#close:active {
	background-position: -32px -128px;
}

These modifiers are just added to give a hover and click effect to the button. The only style changing here is the position of the background which then points to the coordinates of the hover and active states. Put this all together and you have yourself a close button!

I obviously geared the markup for this single example, not taking into account that you may want to reuse the code. With just a small change to select the class of the elements instead of styling based on ID, you can have multiple instances of this button:

a.close {
	display: block;
	height: 14px;
	line-height: 14px;
	font: 11px 'Verdana','Arial',sans-serif;
	padding-left: 20px;
	background: url(sprites.gif) -32px -100px no-repeat;
}
a.close:hover {
	background-position: -32px -114px;
}
a.close:active {
	background-position: -32px -128px;
}

For you newbies: it’s the dot.

Navigation Sprite’ing


This may seem a bit more advanced, but I am using very similar techniques as the example above. Once again, I’ll start off with the markup:

<div id="navigation">
	<ul title="Jon's awesome navigation">
		<li><a href="link1" title="link 1"><span id="nav-first"></span><span>Link 1</span></a></li>
		<li class="splitter"></li>
		<li><a href="link2" title="link 1"><span>Link 2</span></a></li>
		<li class="splitter"></li>
		<li><a href="link3" title="link 1"><span>Link 3</span></a></li>
		<li class="splitter"></li>
		<li><a href="link4" title="link 1"><span>Link 4</span></a></li>
		<li class="splitter"></li>
		<li><a href="link5" title="link 1"><span id="nav-last"></span><span>Link 5</span></a></li>
	</ul>
</div>

Wow that looks like some dirty code. Forgive me for the empty span tags, it’s getting late. I’m assuming everyone’s navigation markup looks pretty similar to this, so it shouldn’t be much of a stretch to update your style sheets. Speaking of which, here they are for this example:

div#navigation {
	font: 11px 'Verdana','Arial',sans-serif;
}
div#navigation ul {
	margin: 0;
	padding: 0;
	height: 50px;
	background: url(sprites.gif) 0 0 repeat-x;
	float: left;
	list-style-type: none;
}
div#navigation ul li {
	float: left;
	display: block;
	width: 50px;
}
div#navigation ul li.splitter {
	width: 2px;
	height: 50px;
	background: url(sprites.gif) -7px -100px no-repeat;
	float: left;
}
div#navigation ul li a {
	display: block;
	height: 50px;
	line-height: 50px;
	color: #606;
	text-decoration: none;
}
div#navigation ul li a:hover {
	background: url(sprites.gif) 0 -50px repeat-x;
	color: #404
}
div#navigation ul li a span	{
	display: block;
	padding: 0 5px;
}
div#navigation ul li a span#nav-first {
	display: block;
	position: absolute;
	padding: 0 !important;
	width: 6px;
	height: 50px;
	background: url(sprites.gif) 0 -100px no-repeat;
}
div#navigation ul li a:hover span#nav-first {
	background: url(sprites.gif) -16px -100px
}
div#navigation ul li a span#nav-last {
	display: block;
	position: absolute;
	margin: 0 0 0 44px;
	padding: 0 !important;
	width: 6px;
	height: 50px;
	background: url(sprites.gif) -10px -100px no-repeat;
}
div#navigation ul li a:hover span#nav-last {
	background: url(sprites.gif) -26px -100px;
}

Quite a bit of styles. It’s okay though, you’ve obviously gone through the first example a million times already, so this should be a breeze.

Now, a lot of the styling is there just for aesthetics so we’ll skip all of that. Let’s just jump to the areas where we’re using sprites:

div#navigation ul {
	margin: 0;
	padding: 0;
	height: 50px;
	background: url(sprites.gif) 0 0 repeat-x;
	float: left;
	list-style-type: none;
}

Here we are actually going to be repeating the sprite as the background in the x direction because I want this navigation bar to expand in the event of new sections. When creating a sprite with the intention of repeating it as a background, keep in mind that they can only be repeated in one direction: x or y. You cannot repeat a slice of a sprite in both directions, otherwise you may have other graphics in the sprite included in the repetition. Looking back at the original sprite, this background can be repeated in the x direction since there are no other slices to the left or right of that area.

div#navigation ul li a:hover {
	background: url(sprites.gif) 0 -50px repeat-x;
	color: #404
}

Skipping all the positioning and font styles, I want to add a hover effect. Once again I’m utilizing a repeating background in the x-direction. The position is found using my marquee technique above.

div#navigation ul li.splitter {
	width: 2px;
	height: 50px;
	background: url(sprites.gif) -7px -100px no-repeat;
	float: left;
}

I thought the navigation bar would look a little weird without having some kind of splitter between each option, so the styles above should take care of that. Here I am actually specifying the width because I do not want the background to repeat.

div#navigation ul li a span#nav-first {
	display: block;
	position: absolute;
	padding: 0 !important;
	width: 6px;
	height: 50px;
	background: url(sprites.gif) 0 -100px no-repeat;
}
div#navigation ul li a:hover span#nav-first {
	background: url(sprites.gif) -16px -100px
}
div#navigation ul li a span#nav-last {
	display: block;
	position: absolute;
	margin: 0 0 0 44px;
	padding: 0 !important;
	width: 6px;
	height: 50px;
	background: url(sprites.gif) -10px -100px no-repeat;
}
div#navigation ul li a:hover span#nav-last {
	background: url(sprites.gif) -26px -100px;
}

Here I’m just being a little fancy and adding the smooth bits at each end of the navigation bar. Essentially the same techniques used above.

Holy Crap!

Yeah, it’s a lot to take in but I didn’t lie when I said this was a beginner guide because I assume everyone reading this is an expert with CSS.

The examples above are merely examples. I hope no one copy-and-pastes the markup because it won’t work for your site (figuratively speaking). I hope you learn from what was presented above, test out your own techniques, and apply it in your daily web development ventures. The best way of learning is to do it yourself, this guide is only here as a guide and also because I have nothing better to do at 2:00AM on a Wednesday morning :)

About the Author

Designer, developer, and excellent napper.