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.