Well, your markup and approach has a few issues – though the biggest issue is I don’t see you actually DECLARING :hover in your CSS, so naturally there’s no hover.
You also are putting the background on the wrong element – you have no width/height on your anchor, so they’re not clickable, and you wouldn’t have :hover available in legacy IE.
First thing I’d do is get you some markup that actually has… TEXT in it for people browsing with images disabled or CSS disabled. That giant negative text-indent being one of the dumbest things you can do to your images-off text. As it sits you’ve got a total accessibility /FAIL/. I would then add some empty spans for gilder-levin image replacement to simplify making the hover states.
<ul id="mainMenu">
<li class="home"><a href="index.html">Home<span></span></a></li>
<li class="about"><a href="about.html">About<span></span></a></li>
<li class="services"><a href="services.html">Services<span></span></a></li>
<li class="sales"><a href="sales.html">Sales<span></span></a></li>
<li class="rentals"><a href="rentals.html">Rentals<span></span></a></li>
<li class="appraisal"><a href="appraisal.html">Appraisal<span></span></a></li>
<li class="tennant"><a href="tennant.html">Tennant<span></span></a></li>
<li class="contact"><a href="contact.php">Contact<span></span></a></li>
<li class="links"><a href="links.html">Links<span></span></a></li>
</ul>
the text is for images off, the spans will be our image versions which will be placed OVER the anchor.
Now the road you were going down would have had you having to state the background-position THREE TIMES for every button. Home for example would need:
.home == background-position:0 0;
.home:hover == background-position:-180px 0;
.home.current == background-position:-360px 0;
That’s a ****load of CSS by the time you are done. I use a different approach where my absolute positioned span gets ‘chopped off’ by an overflow:hidden on the anchor. This means you only say the background-position once per element and then slide the span itself around revealing the other parts.
First order of business is to strip bullets off the ul. I’m going to assume this is a vertical menu so we don’t have to play with float and float wrapping behaviors for now.
#mainMenu {
list-style:none;
}
Now for the LI, I like to strip them of formatting by setting them to display:inline. This prevents oddball height jumping in IE on hover, and the goofy IE7 staircase effect should you decide to float them for a horizontal menu.
#mainMenu li {
display:inline;
}
This means most of the grunt-work has to be done on the anchor.
#mainMenu a {
display:block;
position:relative;
width:180px;
padding:16px 0;
overflow:hidden;
text-decoration:none;
text-align:center;
font:bold 16px/18px arial,helvetica,sans-serif;
color:#FFF;
background:#C60;
}
#mainMenu a:active,
#mainMenu a:focus,
#mainMenu a:hover {
background:#F80; /* need this so IE 6- will actually render state change */
}
Display:block lets us set a width on them, if you are floating for a horizontal menu you can remove that. You can see I do NOT declare a height on them. Heights on elements containing text can often be problematic, and using line-height to try and center our images off text ends up with alignment issues across browsers the taller the line-height – so I just set 18px line height and 16px top/bottom padding. 16+16+18 == 50. The overflow:hidden will chop off anything in our images that are too large. I also set colors similar to the image so that again, images off users aren’t left high and dry.
You can also see I set a background color change on hover. This prevents IE from ‘sticking on’ in the hoverstate, basically ignoring the onmouseout. This also makes it pretty for images off users.
The span gets kind of interesting.
#mainMenu a span {
position:absolute;
display:inline; /* display state change fixes IE 7 hover bug */
top:0;
left:0;
width:540px;
height:450px;
background:url(images/naviv.png) 0 0 no-repeat;
}
The absolute positioning ends up treating 0:0 as the upper left corner of the anchor around it since the anchor is position:relative. I set it to 0:0 as the default, then set the width and height equal to the image you are using as the replacement. This means we don’t have to slide the background-image around at all, and can slide the span around instead – again, all that extra width and height is cut off by the overflow.
To hover, we just need to slide it left 180px.
#mainMenu a:active span,
#mainMenu a:focus span,
#mainMenu a:hover span {
display:block; /* display state change fixes IE 7 hover bug */
left:-180px;
}
You’ll notice I set display:inline on the span, and change it to block on the hover state. IE7 can be a real dipshit sometimes on this stuff, and unless the ‘state’ changes, it will ignore the hover. Absolute positioned elements are by definition inherently ‘block’, so setting display:inline should have zero effect, but becuase it ‘changes’ from inline to block, IE7 for some reason decides to behave. (idiocy, pure and simple)
The ‘current’ state is just positioned left. Because it’s not a psuedostate the block we set on the anchor is just fine.
#mainMenu .current span {
left:-360px;
}
The rest of it is the same idea, just using ‘top’ instead of ‘left’ for each of your unique classes.
#mainMenu .home span {
top:0;
}
#mainMenu .about span {
top:-50px;
}
#mainMenu .services span {
top:-100px;
}
#mainMenu .sales span {
top:-150px;
}
#mainMenu .rentals span {
top:-200px;
}
#mainMenu .appraisal span {
top:-250px;
}
#mainMenu .tennant span {
top:-300px;
}
#mainMenu .contact span {
top:-350px;
}
#mainMenu .links span {
top:-400px;
}
… and that’s it. I tossed a demo copy up on my server for you to see it in action.
http://www.cutcodedown.com/for_others/airFor/template.html
I find this technique simpler to work with, and that it actually works perfect with images disabled and CSS still on is a big bonus – and it’s generally less code than stating each and every possible background-position combination.
Hope this helps – you need more explanation, ask away. I know the various IE fixes complicate what should be something simple a bit.
– edit – oops, Paul beat me to the punch… though I think he’ll get a good laugh out of my approach since it’s a lot less code and a different way of handling it.
Though he’s using :focus which isn’t exactly an ‘active’ state… which is best done either with a class on body and dual inheritance (sloppy IMHO) or using a ‘current’ class to indicate the ‘current’ page as I did.
using :focus is… well, usually I set that the same as :hover. You can see I set :active and :focus the same since that traps all keyboard navigators across all browsers. An “active” page, as in the current page being viewed cannot be set by CSS alone, you’ve got to say which one it is in the markup… and it’s also NOT what :active or :focus MEANS.