CSS Menus With Images - CSS Sprites
In this tutorial I will show you how to build a CSS menu with images as menu items using a CSS tecnique that’s known with the name of CSS sprites. We’ll start from the graphic creation in Photoshop and then code it in HTML and CSS.
Before we start, you can:
- see the CSS menu we’re going to build
- download the source files (Photoshop file included)
Warning: if the download link doesn’t work, please send me an e-mail so I can fix it. Thanks in advance ;)
Why Build a Menu With Images?
The answer is obvious: to do things you couldn’t do with plain text, like using a texture, a non web-safe font or to create a little more sophisticated hover effect.
CSS Sprites
The best way to build a menu with images is by using a CSS tecnique called CSS sprites. This tecnique consists in using combined images; in the specific case of menus, the CSS sprite combines the graphic images of both the link’s normal state and the hover state.
Why is it convenient to combine two images together? For one, it helps stay us organized (by using CSS sprites we need half of the images we would need by not using them), but more importantly it cuts in half the number of requests sent to the server, reducing the overall time it takes for the page to load.
The Photoshop File
Open a new document at 800×400px. Our menu will be smaller, but let’s keep some extra space for our convenience.
Menu Background
Select the Rectangular Marquee tool from the toolbar, then choose Fixed Size from the Style dropdown menu in the tool options bar. Choose 550px for the width and 50px for the height. This will be the menu size.
Add a new layer by going to Levels > New > Level or clicking on the second icon from the right at the bottom of the Layer palette. Now click anywhere on the document canvas to get a 550×50px rectangular selection. It’s not necessary that it’s perfectly centered but try to go for the center anyway. Create guides around the selection.
![]()
Choose a color for the menu background. I went for a dark brown (#514537). Select the Rounded Rectangle tool and make sure that the Shape Layers mode is selected in the tool options bar.
While the rounded rectangle tool is selected, place the cursor over the top left corner of the rectangle created by the four guides, then drag towards the opposite bottom right corner. You should get something like this:
This rectangle will work as the menu background. As a last touch, let’s apply a subtle gradient. Click twice over the rounded rectangle layer to get the Layer Styles window to pop up, and check the Gradient Overlay style in the left column. Click twice on the gradient colors bar, then choose the same color you used for the background as the two colors of the gradient, but make the second one lighter.
If you’re using the same brown I picked, choose a lighter brown (#71604d) as the second color. This is what you get:
Remember that the secret to a good gradient is subtlety. Don’t you fade a midnight dark blue into a midday light blue or a vivid red into a pale pink. The second color must be just a little lighter than the first one.
The Menu Items
We can now take care of the menu items. Our menu has five items: Tutorial, Siti CSS, Risorse, Showcase and Offtopic (the items are in Italian because this is the translation of a tutorial previously written for the Italian blog. This should be no problem to your understanding though).
The menu is 550px wide, so each menu item’s width will be equal to 550 / 5 = 110px. Create a 110×50px rectangular selection (the height is the same as the menu’s) and drag it to the top left corner of the menu background, then create a guide to its right:
Do the same for each menu item until you will have created all necessary guides. Be pixel perfect while creating guides: this will be essential when we’ll slice the images later.
Now for the items. Select the Type tool and choose a font you like; I picked a condensed font called Bebas. Write the five menu items using font size and color appropriate to the background menu you’ve created. If you’re following my lead, select 18px as the font size and white as the color.
We want text to be perfectly centered in each of the five cells created by the guides. To do so, write the menu item, the Tutorial one for example. Create a new 110×50px rectangular selection and place it exactly over the first cell until the selection perfectly snaps to the guides. Select then the Marquee tool from the toolbar (or by pressing V on the keyboard) and in the tool options bar click the Align Vertical Centers icon first and then the Align Horizontal Centers one (they’re highlighted in red in the following image):
Doing so aligns the text at the center of the cell:
Repeat these same steps for each menu item. Tip: to avoid to repeat the horizontal alignment for each menu, duplicate the first text item, replace the text as needed and then move it rightwards using the directional arrows. You’re going to have to align the items vertically everytime, sorry!
Once you’re done, you should have something like this:
Tip: group the items together and name the group (what about Items?). This is an easy tutorial and we’re only dealing with a few layers, but when you’re working on a real project layers easily stack up - renaming them and grouping them is a best practice to stay organized and improve your workflow.
The Hover Effect
The “hardest” part of the job is behind us already. We’re left with creating the hover effect, and that’s just easy. Group all the layers you have so far (except for the white background layer), name it Normal State or something like that, then duplicate it by right-clicking on the group and selecting Duplicate Group from the contextual flyout menu. Rename the group in something like Hover State.
Move the duplicated group upwards until the bottom border of the background menu in the duplicated group is perfectly adjacent to the top border of the background menu in the original group (there must not be any distance between them, not even one pixel). See the following image for reference:
We create the hover effect by changing the text color. I picked an orange (#ffcc00), and here is what I got:
Slicing The Images
It’s time to slice the images needed for the menu. The guides are all there already, you just have to add another one on top of the duplicated menu. Once again, be precise when creating guides: zoom in the page with the Zoom tool if needed.
Select the Crop tool in the toolbar (or by pressing C on the keyboard) and select the first rectangle, the one for the Tutorial menu item:
Accuracy is essential in this step too: the crop area should be exactly as wide as the area surrounded by the guides. Zoom in the page to have a better vision.
Once you’ve created the selection, hit Enter. Only the cropped area will be left in your document. Hide the white background layer in the Layer palette: the first and last menu items have two rounded rectangles each through which you can see the background; if we ever changed the background to a different color those white small bits would be visible, and that’s not what we want. This is the same reason why you should save the menu images in .png format.
You’re now ready to save the image, but before you do that, create a root folder for this project and a subfolder called Images: this is where you will save the sliced images. Save them in .png format.
Repeat this process to slice each and every image sprite needed for the menu. Once you’re done, you should have five images in your image folder.
Alright, we’re done with Photoshop and ready to move on to HTML/CSS coding!
The HTML Code
Open a new HTML document in the text editor of your choice. The most semantic HTML code to use for a menu is a list as a menu is actually a list of items. It’s also necessary to add a class to each link because we’re using different images - I’ll explain this later in greater detail.
<ul>
<li><a href="@" class="tutorial">Tutorial</a></li>
<li><a href="@" class="siticss">Siti CSS</a></li>
<li><a href="@" class="risorse">Risorse</a></li>
<li><a href="@" class="showcase">Showcase</a></li>
<li><a href="@" class="offtopic">Off topic</a></li>
</ul>
The CSS: The Theory
Here is what we’ll do with CSS: we’ll start by zeroing all default margins and paddings of the list, then we’ll float the <li> next to each other. The rest of the job will all be about the links: we’ll apply the image sprites we’ve created as backgrounds and create the hover effect by playing with the image background position.
The CSS: The Practice
Create a new CSS file and save it in the root folder, then add the following lines:
ul {
margin: 0;
padding: 0;
list-style-type: none; }
li { float:left; }
What we need to do next is to turn links from inline elements in block elements so that we can assign them fixed sizes (if you want to know more about inline and block elements you can read this tutorial about the display property and its values).
a { display: block; }
How big should links be? Each of the image sprites we’ve created is 110px wide and 100px tall. Image sprites include both the normal state image and the hover state image though, while we only want to display the latter on mouse hover. This means we only want to show one half of the image and hide the other half until we hover it. For this purpose, we can go with the image width as it is but we must cut the height in half:
a {
width: 110px;
height: 50px; }
Did you ever notice that after clicking a menu item a dotted border is displayed around it? That’s a system to let users know they clicked on something, but in some browsers this border runs across the page rather than just sticking around the menu item. To prevent this from happening, we can add the overflow property in the CSS file:
a { overflow: hidden; }
We should also hide the text so that the image is the only thing displayed. We can do this by shifting the text to the left:
text-indent:-9999px;
The text is usually shifted by 9999 pixels so that it’s not visible even with large screen resolutions. Why not deleting it completely anyway? Because of accessibility issues: if CSS are disabled for any reasons, the user can still read the text link instead of the image.
The Image Sprites As Link Backgrounds
It’s time to assign the image sprites as the links backgrounds.
There are several CSS properties that relate to the use of image backgrounds. In this tutorial we’re going to use three of them:
- background-repeat lets us decide if we want the image to repeat or not;
- background-position lets us set the image position.
- background-image lets us insert the path to the image sprite we want to use as a background.
Background-repeat
We would need the image to repeat if for instance we were using a pattern as a background image. For the purpose of this tutorial though, we don’t need the image to repeat:
a { background-repeat: no-repeat; }
Background-position
The concept behind background-position is a little complex, so pay attention - but don’t be scared!
Let’s consider a single item menu, the Tutorial one. The image sprite for this item is 110px wide and 100px tall. We have agreed we should only display half the image though, which equals to a 110×50px area, and hide the rest until we need it. It’s like this area is the glass of a picture frame: it allows us to see the part of the picture under the glass but covers the part under the frame.
The CSS sprite techniques works pretty much in the same way. We have a picture (the image sprite) and we have a glass (the 110×50px link area) that shows a half of the picture (the normal state half of the image sprite) and hides the other half (the hover state half of the image sprite). The question is, how do we move the picture so that the second half is visible when we hover the menu item?
Enters the background-position. The purpose of this property is in fact to move the background image of an element. But in relation to what should we move it? We need a reference point, which is the top left corner of the link area (see the image for reference).
The background-position property takes two values: the distance of the image from the left of the reference point; and the distance of the image from the top of the reference point. Both values are 0 by default, which means that the top left corner of the background image will perfectly overlap the top left corner of the link area.
Take a look at this image. You can see the 110×50px link area only allows us to see half of the background image. But, wait a second, it’s the hover state half, not the normal state one - how comes?
That’s because we haven’t assigned the background-position property to the link yet, so its default values are 0. To display the other half we should modify the background-position values.
background-position:0 -50px;
And here is what we get:
I’m sure you guess what should we do to generate the hover effect. Take a second to think about it…
a:hover { background-position: 0 0; }
Did you guess? Bravo!
Background-image
Let’s recap all the CSS code we wrote so far:
a {
display: block;
overflow: hidden;
width: 110px;
height: 50px;
text-indent:-9999px;
background-repeat: no-repeat;
background-position: 0 -50px; }
a:hover { background-position: 0 0; }
The only thing left is to assign each image sprite to its respective menu item. We can do so taking advantage of the classes we assigned in the HTML code:
a.tutorial { background-image:url(immagini/tutorial.png); }
a.siticss { background-image:url(immagini/siti-css.png); }
a.risorse { background-image:url(immagini/risorse.png); }
a.showcase { background-image:url(immagini/showcase.png); }
a.offtopic { background-image:url(immagini/off-topic.png); }
Images With Differents Widths
In this tutorial we have built a menu with images which all have the same width. But what if each image had a different width? In such a case, it’s enough to declare each image width in the group of properties assigned to the respective link classes (the ones for which we assign the background images).
The last code snippet we’ve written would therefore become as following:
a.tutorial {
width:100px;
background-image:url(immagini/tutorial.png); }
a.siticss {
width:70px;
background-image:url(immagini/siti-css.png); }
a.risorse {
width:83px;
background-image:url(immagini/risorse.png); }
a.showcase {
width:89px;
background-image:url(immagini/showcase.png); }
a.offtopic {
width:94px;
background-image:url(immagini/off-topic.png); }
That’s It, Folks!
This is the final result. I realize it’s quite a long tutorial but I went in deep detail so that you could really grasp how the CSS sprite technique works. Don’t panic anyway: after a few trials it’ll be easier and more intuitive for you to use.
So, what do you think?
Did you find this tutorial useful? Do you have questions to ask? Share your thoughts in the comments!
Good post. For greater accessibility I’d recommend looking at JS-powered tool called StateScope (more information is available on my blog - http://blog.apluswebcreations.com/2009/04/09/the-perfect-solution-for-image-replacement/). The reason is because if users have CSS enabled but images disabled, all they see on a menu like the one you created is, well, nothing. StateScope fixes this issue and I’ve found it quite useful in my projects.
I’d be interested in your thoughts on the matter…
Slightly off-topic, I really like your design. I’m envious as I’m one of those developers who can’t design to save my life!
July 31, 2009 at 2:32 pm
Good in depth tutorial. Wouldn’t be better to have just used a single image instead five different ones?
July 31, 2009 at 4:25 pm
@Mike - What you’ve pointed out is true and it actually is a drawback of using this technique, but there are otehr CSS sprites techniques that allow to view text if images are disabled, so I think I would go with one of those rather than using Javascript.
@Los - I’ve used five different images because the text on each image is different (and the first and last ones have rounded corners too).
July 31, 2009 at 7:37 pm
@grazz - IMO the other options have as many cons as using the JavaScript option. With this method (State Scope) the ONLY con is if the user does not have JavaScript enabled. If they don’t, they still get a fully-accessible page with all elements that had background graphics applied to them visible.
You can, in essence, create two environments for the user - the one that is graphic intensive for the JavaScript-enabled user and then the one that is a cleaner non-graphic based version for the JavaScript-disabled user.
July 31, 2009 at 8:04 pm
Good article very clear. But I am also wondering why you sliced this image up? This could have easily been done with only one image, which is the whole point of using sprites in the first place, less http requests to the server. In my opinion, it would have been more efficient to have one large sprite instead of 5 smaller ones. Either way though the end effect is the same.
Good job
August 2, 2009 at 11:49 pm
I would have used one image if the menu items were text links, but they’re part of the image too. Plus the first and last one have rounded corners.
August 3, 2009 at 8:45 am
[...] CSS Menus With Images - CSS Sprites « Blogging CSSbloggingcss.com [...]
August 3, 2009 at 10:20 am
Nice tutorial…very clearly explained.
August 3, 2009 at 11:36 am
Los and Rick are not suggesting to use the same individual menu image, but rather to use the whole rack as a unit with the horizontal background-position parameter controlling where along the image the appropriate portion of the menu is displayed.
August 3, 2009 at 12:28 pm
you can use one image for the whole menu, this way you limit the number of http requests.
August 3, 2009 at 12:31 pm
[...] – Project Hosting on Google Code Web de jEsuSdA Tutoriales de Diseo Grfico con Gimp CSS Menus With Images – CSS Sprites Blogging CSS [...]
August 3, 2009 at 1:44 pm
Your text-indent:-9999px; will generate a google ban :)
August 3, 2009 at 3:15 pm
Why not just wrap the text with a and set it to display:none? Simple and easy! (it will NOT result in a Google ban)
August 3, 2009 at 3:43 pm
You can still use one single image, even if the images use text / rounded corners.
You simply have specify the background position for each a.class
Example here:
http://www.electrictoolbox.com/css-sprites-image-navigation/
August 3, 2009 at 6:33 pm
Okay, you all are right, I was missing your point, sorry :) It’s true, I could’ve used one single image. I’ll try to add this solution in the tutorial.
Thank you guys!
August 3, 2009 at 7:39 pm
[...] CSS Menus With Images - CSS Sprites (tags: css webdesign tutorials sprites) [...]
August 7, 2009 at 3:30 pm
Thank you for the tutorial. Its very helpful :)
August 9, 2009 at 4:20 am
I often have horrible luck with online tutorials. But yours worked great for me. Easy to understand, easy to follow, you didn’t skip steps, and I was able to see where I should modify the code for my particular menu and images. Awesome, and thanks very much!
August 20, 2009 at 8:58 pm