Accessibility Navigation

Graphical CSS Rollover Menu

Posted on 4th March 2009 by Jacob

In my previous post about CSS image rollovers we touched briefly on how to create more advanced menu systems using the CSS rollover technique. Let’s now take a deeper look to see the advanced menu in action.

We looked previously at the Apple menu and how they use a single image sprite to run their menu system.

Apple.com navigation image sprite

They include all four states of the navigation bar into a single image and then transition between them when a user hovers, clicks or views a section.

Creating our own menu

As an example we will create our own little menu bar in photoshop that could be used on a website.

Menu Sprite Image

Here we have a single image containing our three different menu sections (home, blog, contact) and the four different states that the menu could be in: normal, hover, clicked and active.

Creating the code

The following case may look long and complex, but it is really very simple and can be broken up into four sections which have been commented in the CSS. Within our image sprite each image is 150px x 44px and you will see these dimensions used throughout the CSS.

CSS Code

/*
*	Setup
*/
ul.cssmenu {
	list-style: none;
	padding: 0px;
	}

.displace {
	position: absolute;
	left: -5000px;
	}

ul.cssmenu li {
	float: left;
	}

ul.cssmenu li a {
	display: block;
	width: 150px;
	height: 44px;
	background: url('sprite.gif');
	}

/*
*	Normal Links
*/
ul.cssmenu li.home a {
	background-position: 0 0;
	}

ul.cssmenu li.blog a {
	background-position: -150px 0;
	}

ul.cssmenu li.contact a {
	background-position: -300px 0;
	}

/*
*	Hover Links
*/
ul.cssmenu li.home a:hover {
	background-position: 0 -44px;
	}

ul.cssmenu li.blog a:hover {
	background-position: -150px -44px;
	}

ul.cssmenu li.contact a:hover {
	background-position: -300px -44px;
	}

/*
*	Clicked Links
*/
ul.cssmenu li.home a:active {
	background-position: 0 -88px;
	}

ul.cssmenu li.blog a:active {
	background-position: -150px -88px;
	}

ul.cssmenu li.contact a:active {
	background-position: -300px -88px;
	}

/*
*	Selected/Active Links
*/
ul.cssmenu li.home a.selected {
	background-position: 0 -132px;
	}

ul.cssmenu li.blog a.selected {
	background-position: -150px -132px;
	}

ul.cssmenu li.contact a.selected {
	background-position: -300px -132px;
	}

We first setup some basic classes to style an unordered list and to displace text off the screen for use with screen readers and users without CSS. Within ‘ul.cssmenu li a‘ we then set the dimensions of each menu item to be 150px x 44px and provide the background image.

The next three areas of the CSS are simply different link selectors for the different actions that the button goes through. For each of the different actions we move the background position down 44px as this is the height of our image and so relates to where the next image begins. If you leave gaps between your images then you will have to adjust the background position accordingly.

The final section provides a class called ‘selected‘ that we will use to indicate the current page we are on.

HTML Code

<ul class="cssmenu">
	<li class="home"><a href="#" class="selected" title="Home"><span class="displace">Home</span></a></li>
	<li class="blog"><a href="#" title="Blog"><span class="displace">Blog</span></a></li>
	<li class="contact"><a href="#" title="Contact"><span class="displace">Contact</span></a></li>
</ul>

The HTML code is a very basic unordered list with our styles attached. The current active menu item is given the ‘selected‘ class.

We have included a <span> tag with a text alternative to the image and displaced it off the side of the visible screen so that screenreaders will read it.

Without CSS enabled users will just see a nicely formatted list of menu items with text links, with CSS you will see a graphical menu like the one below!

The Result

The following link tree is the example of a CSS rollover menu. You cannot see the example function unless you have CSS enabled. If you are reading this in an RSS reader or external site you may need to visit the site to see a functioning menu.



As you can see hovering over the menu above changes the background image from blue to red, clicking then changes it to green. The home menu item has been given the ‘selected‘ class and so remains orange throughout.


Have Your Say

Have Your Say Form









Comments

  • Marko on 4th March 2009 wrote:

    That’s brilliant stuff. It works great. Exactly what I was looking for, and you wrote the tutorial so quickly. Thank you so much.


  • daz on 5th March 2009 wrote:

    That is absolutely great, something I really needed to know and when I did the first tutorial I was already wondering how to do it like this. You saved me hours.
    A nice clean easy to follow tutorial that works perfect first time. Thanks.


  • Jung on 16th March 2009 wrote:

    This is exactly what I was looking for. It’s so simple! Thank you very much.


  • ChrisG on 12th April 2009 wrote:

    Any insights on making this work with IE 6?


  • ChrisG on 12th April 2009 wrote:

    I apologize – it works great in IE 6. I found my mistake


  • arif on 13th April 2009 wrote:

    This is absoloutely GREAT- I just need the same affect on a horizontal menu bar rather than a vertical block. so please tell me what do i use instead of unordered list. I am a bit weak on html and css, but i eventually find my way with some help.
    Thank you.


  • arif on 14th April 2009 wrote:

    ignore my earlier twadle – i managed to get your example to work – it does what i was asking, only took 5-hours!! css and browser seem very touchy, mine only worked after i removed html comments and a few other tweaks. i can see it to be great, but just hope i can get it work for my site properly.
    Thank You.


  • arif on 14th April 2009 wrote:

    PROBLEM –
    I encountered is, how to make the active image stick? I have a home page, with rollover menu in a page header (via php include command), upon selection this menu sends the user to the called linked eg. page2. Now page2 also contains the same page header via php include command which has the original css rollover – Problem is on page2 we go back to initial state of rollover ie. the selection from homepage is not highlighted(relevant image sprite not activated) on page-2! Any Solution?

    Your help is appreciated.

    thanks.


  • Jhonny Cahuaya H. on 27th April 2009 wrote:

    Hola por favor me pueden mandar el codigo completo con las imagenes


  • Akino on 8th May 2009 wrote:

    Amazing


  • Chris on 12th May 2009 wrote:

    hello, I’m really one of the biggest funs of your website. You are superb!!!

    I have exactly same problem as Arif. how can we activate the orange button for each button? when we click on another section, the orange link is not activated. and with wordpress im using the same header for my all pages. is there any solution?


  • Jacob on 12th May 2009 wrote:

    @chris – you just have to have a variable that tracks what page you are on and marks that specific menu item as being selected.

    In a wordpress template you can find the current category that you are on with the ‘the_category()’ template tag. You can then use this value in a switch statement to figure out which item should be given the ‘selected’ class.


  • didli on 15th May 2009 wrote:

    This is amazing ! Exactly what I was looking to do for hours !
    Thank you !


  • esch on 16th May 2009 wrote:

    One thing I noticed is that I now have to position the whole menu bar absolutely. I need to have my horizontal bar stay to the baseline as the parent container height grows. Any suggestions?


  • Anna on 25th May 2009 wrote:

    Amazing. Just what I was looking for. Thank You.


  • MrStupid on 28th May 2009 wrote:

    WOW. This post has been absolutely amazing. Just wow. Again, wow.


  • Erik Arckens on 1st June 2009 wrote:

    How do you suggest I include a php function call for an email form (basically it is this -without the < tags-: ?=createMailto(‘info@mysafety.be’)?).


  • 2220 on 2nd July 2009 wrote:

    outline:none;

    to avoid the blue or red dotted boxes around clicked links in FF


  • Titus on 10th July 2009 wrote:

    any way to have the hover state change two images on the page e.g. the menu item state and a preview image?


  • John Wiltshire on 28th July 2009 wrote:

    Really good stuff – thanks.
    I had to fiddle about to remove the indent from the UL element to make my menu sit correctly in position in IE7. I added the padding and margin elements and it worked:

    ul.cssmenu {
    float: left;
    padding: 0;
    margin: 0;

    }

    .displace {
    float: left;
    }

    ul.cssmenu li {
    float: left;
    padding: 0;
    margin: 0;
    }

    Hope that helps.

    Thanks again.


  • John Wiltshire on 28th July 2009 wrote:

    Just an extra note – I had bullets showing up in Firefox so added the following

    ul.cssmenu {
    float: left;
    padding: 0;
    margin: 0;
    list-style-type: none;
    }

    List-style-type: none got rid of the bullets which defaulted to circles.


  • yy1993 on 6th August 2009 wrote:

    Thanks for that!


  • Sarah on 22nd August 2009 wrote:

    This tutorial is great, very easy to understand and was exactly what I was looking for. Question, though: How can I get the menu centered on the page? I tried changing float: to center, but it just lines up the images on top of each other in the center instead of in a row, and tags don’t work. Ideas? Thanks!


  • Sarah on 22nd August 2009 wrote:

    It didn’t show up in my previous comment, but i meant the center tags didn’t work.


  • Jacob on 22nd August 2009 wrote:

    @Sarah – You will need to put the menu in a div and then give it a width and set the margin to auto.


  • Sarah on 23rd August 2009 wrote:

    @Jacob Thanks so much! It worked.


  • Casey on 4th September 2009 wrote:

    Thanks for this information. My navigation images are all different widths. Is there any way to work with that?


  • Jacob on 5th September 2009 wrote:

    @casey – Yes you just need to set the width and height for each item and then change the background-positions relative to those dimensions.


  • Dave on 23rd October 2009 wrote:

    Great tutorial! Worked very well!

    Just as a side note, with my setup, it worked better for “Hover” to hover over the “Selected” as well. So if you are looking to do this, just put the “Selected” CSS portion ABOVE the “Hover” CSS potion in the code.

    Dave


  • Frank on 29th October 2009 wrote:

    Great tutorial!!

    Is there an easy way to have the green button (under ‘blog’ or ‘contact’) stay visible when clicked? (so people know on what page they are)
    I saw other people mentioning this option, but there was no (to me) clear answer?

    Thanks!


  • Jacob on 29th October 2009 wrote:

    @Frank – When you click on a menu item the a:active settings will take over to show that its being clicked. This will then usually take you to a new page as its a link. On this new page you need to state which menu item is to be highlighted for this page by giving it the appropriate class:

    <a href=”#” class=”selected” title=”Home”>

    You need to change which menu item is given the “selected” class for each page you are on.

    The green button on my example is just an indication that the item was clicked, much the same as a button will change to look indented and pressed in when clicked.


  • Jacob on 29th October 2009 wrote:

    @Frank – Yes so you just have to change the included navigation to check for which page is active and then give it the required CSS class.

    If your getting the menu items from a DB then its fairly easy to add a check to the loop that gets the menu items – the same is true with a WordPress template. If the menu include is just static HTML, then you will need to update it to either use some scripting language to process it or include different files for each active menu.

    Alternatively you could use JS to do the same thing, but of course that will only work for users who have JS enabled.


  • Frank on 30th October 2009 wrote:

    Great – I’m looking into it.

    Thanks!


  • Nikky on 12th November 2009 wrote:

    This tutorial is fantastic! Thank you for posting it, I’m going to have a play around with it now. I have always just used the java rollover buttons, but its not helping my SEO. Will this way of creating buttons be more SEO friendly? Will google actually recognize I have links now rather than ignoring them?

    Thanks again!


  • marketing belfast on 10th December 2009 wrote:

    I have tried using this CSS rollover and it makes me wonder how could you possibly doing it without problems cause i encounter so many errors while doing it.


  • laura on 20th December 2009 wrote:

    clearest tutorial i’ve seen on the topic. thx!


  • Andrew on 21st December 2009 wrote:

    That’s an awesome technique – thanks!


  • Jimothy James on 24th December 2009 wrote:

    Has anyone figured out how to use this with wordpress?

    re:”In a wordpress template you can find the current category that you are on with the ‘the_category()’ template tag. You can then use this value in a switch statement to figure out which item should be given the ’selected’ class.”

    how do you do that exactly?


  • Brian Dempsey on 23rd February 2010 wrote:

    Absolutely love this post!

    Question: It looks like it will only work if every button is the same width. In the example above 150px. I have a nav bar with 10 buttons and every one of them is a different size.

    How does it work in that situation? Thanks for the help!


  • Jacob on 23rd February 2010 wrote:

    @brian Yes it can work with different sized buttons – you just have to give a width and height for each item.


  • Brian Dempsey on 23rd February 2010 wrote:

    @Jacob,

    Looking at the code, I see:

    ul.cssmenu li a {
    display: block;
    width: 75px;
    height: 38px;
    background: url(‘img/navbar.jpg’);
    }

    This is where the default height / width is set for each link. All of the buttons are the same height. I just need to change the width. So do I simply move the width attribute to each individual link like this:

    ul.cssmenu li.homea {
    background-position: 0 0;
    width: 75px;
    }

    Or do I need to add the display: block and height there as well?

    Thanks for the help. This is a great script!


  • Jacob on 23rd February 2010 wrote:

    @brian – Yep that’s right- just double check in your browser that it works as expected.


  • astatic on 22nd March 2010 wrote:

    You’ve saved me hours of stress and frustration…can’t thank you enough. I’m a relative CSS newbie and this made my life SO much easier.


  • Nicky on 30th March 2010 wrote:

    I’m sorry, this is very new to me – where do you put the html section? On each individual page?


  • smenglish on 16th April 2010 wrote:

    how do i center the nav bar? Please help!


  • smenglish on 19th April 2010 wrote:

    Hi, I was wondering If it was possible to be able to put a border around the nav bar?


  • bayan on 21st April 2010 wrote:

    hello every one
    Really nice, and it’s my dream to make menu bar like apple.
    But i have problem in joomla 1.5, i tried to make it through jumi module,but alot of errors ( the font became smaller on page,space became bigger..etc)
    Please help me to do it in joomla pleaaasseeeee.


  • Jacob on 29th April 2010 wrote:

    @Nicky – Yes put the HTML for the menu on any page where you want the menu to be.

    @smenglish – You center a div by using ‘margin: auto’ and giving the whole outer div a defined width. To put a border around it just use ‘border: 1px solid #000′ etc – or add the border to the images if you want something more fancy.

    @bayan – I dont know joolma well, but it sounds like there is a conflic with the CSS, your template probably already has elements with the same ID’s and class names – try renaming the ones for the menu to something more unique and see what happens.


  • Mikey S on 25th May 2010 wrote:

    Another wicked tutorial, Jacob. I’m tempted to make a new website this way…

    But like in the last tutorial, I can’t help but notice the ‘annoying’ 1px dotted border that shows around each button when you click it.

    It is not a huge problem here (barely visible in fact), but my site has a dark background and this border sticks out like a sore thumb.

    I’ve been hopeless trying to get rid of it using CSS. I think my problem is that I don’t know where to apply the “border: none;” value – it shows no effect when applied to “a” or “a img” – something I used on my other sites to get rid of the border…


  • Jeff B on 4th June 2010 wrote:

    Good tutorial. Everything works except my selected state. I made sure to add the class=”selected” on my 2nd page for my 1st menu item.

    Triple checked everything else and it still won’t show up.


  • Wed on 12th June 2010 wrote:

    The original code worked like a charm. But I expanded the buttons to eight, drew a new picture and recalculated. Then it all collapsed. Now it shows eight rows, each shifted one button to the left. Except for the last three, which are starting as normal. Is this a limit to the technique?


  • Jacob on 12th June 2010 wrote:

    @wed – No there is no limit – you just have to ensure that the width of your menu items isnt larger than the width of the parent div.


  • Wed on 12th June 2010 wrote:

    Thanks a lot for the response. I believe the div is 800px and the sprite (named stripe.png) 640. I missed adding the unit px from the beginning. But the difference was not significant. The result can be seen here: http://www.syntaxsociety.se/~wed/csstest/page.html


  • Sean on 30th June 2010 wrote:

    Hi, i’m having a problem getting the navbar into another div to center it within the parent div, the navbar just stays there. Please help.


  • Jenn on 7th July 2010 wrote:

    I currently have a background image which repeats across the top of the page, would this conflict it in any way. My page is acting like the buttons are there, but the images are not appearing.


  • Harold on 14th July 2010 wrote:

    Got this working but as a couple others have said I can’t get my menu centered. If I change the float to center it just puts one image on top of the other. So as was suggested both times I made a div class called “sidemenu” with a width of 100% and a margin of auto. Nothing changes. What am I doing wrong? Please help. This is the code I made for the div to get it centered. Maybe I did that wrong?

    div.sidemenu {
    width: auto;
    margin: auto;
    }


  • Harold on 14th July 2010 wrote:

    I posted the wrong code. This is the code I made to get the menu to center with no luck. :( Please help.

    div.sidemenu {
    width: 100%;
    margin: auto;
    }


  • Corey on 16th July 2010 wrote:

    This tutorial work fine and all, but placing it using a tag is a pain. When I try to give it an absolute position inside a parent box the button appears lower than I expected. Setting position to relative seemed to fix this problem, but then when I go to place an identical button in a nothing position the positioning is distorted.


  • anton on 18th July 2010 wrote:

    Hi. Thanks for this tutorial.
    I am a beginner however and have a problem figuring out how to do the different size buttons. I know you told Casey to give them width and height, but where do i do that? In the CSS? under what?
    Please someone explain it for a beginner. Thanks a lot!


  • anton on 18th July 2010 wrote:

    Correction. i tried to do what Brian had done but i’m having issues.
    1. i had to float to the right the whole menu and it looks like it’s reversing the info for the links.
    2. my image appears as 2 images staggered over one another.
    the height is good, but i’m having issues with the width.
    and again, my links are different widths as brian’s.
    brian, do you have your website up so i can look at your code? thanks all!


  • Web Design Northern Ireland on 26th July 2010 wrote:

    Sprites in a menu! great for page load times and enhancing your SEO. Google seems to be rewarding those who aim for less http requests and faster server speeds.