Rollover Navigation for fun and profit.

Gone are the days when a nicely-styled text link was sufficient for main navigation. Heck, designs are even sporting graphical sub navigation these days. While this is a pain in the proverbial backside for easy updating, it’s what life has given us. And when life gives us graphics and demands SEO compatibility and semantically correct HTML, we make lemonade. And then we charge $125/cup.

So, how do we tackle this without all of that pesky JavaScript which is likely to break on any given browser (I’m glaring at you, IE6. And IE7. And IE8. And Firefox. And particularly Safari.) More to the point, how do we do this in a way that’s not just images and can actually be picked up by search engines? We say Screw the JavaScript! (I say that a lot.) The W3C has given us all the tools we need with HTML and CSS! We just need to find new and interesting ways to abuse them.

The root of the issue here is that we have an image that we want to change when we mouse over it, AND we want text to show up for spiders. The Spider isn’t going to understand nav_contact.gif as well as it will understand Contact Doylestown Web Design, so we need to scrap the image tag altogether. We also need to put that text in there and not have it display. These two things are not quite intuitive, but hey, we’re left brain geniuses, are we not?

So, here’s our HTML construct:

  <div id="navigation">
   <ul>
    <li id="nav_01"><a href="/item_1.htm" title="Top Item 1">Top Item 1</a></li>
    <li id="nav_02"><a href="/item_2.htm" title="Top Item 2">Top Item 2</a></li>
    <li id="nav_03"><a href="/item_3.htm" title="Top Item 3">Top Item 3</a></li>
    <li id="nav_04"><a href="/item_4.htm" title="Top Item 4">Top Item 4</a></li>
    <li id="nav_05"><a href="/item_5.htm" title="Top Item 5">Top Item 5</a></li>
   </ul>
  </div>

What we have here is a container <div>, an unordered list, and list tags with links inside. Now, that’s not going to look very good if we leave it like that, so off to the CSS we go.

First, we need to set the stage with the width, height, and background:

#navigation {
	width:740px;
	height:30px;
	background:url(/images/navigation.jpg) top left no-repeat;
}

For that background image, you want to have your entire navigation as it looks normally. No need to cut up individual images for your default state!

Next, we need to whip that list into shape:

#navigation ul {
	width:740px;
	height:30px;
	margin:0px;
	padding:0px;
	list-style:none;
}

We make sure that the <ul> tag is the same exact dimensions as our containing div, and then strip all the margins, padding, and bullets from it. Viola, no more list! Just a happy semantic construct.

Now, we need to trim the <li> tags:

#navigation ul li {
	height:30px;
	margin:0px;
	padding:0px;
	list-style:none;
	float:left;
	display:block;
}

Define the height (because this is horizontal, and they’ll all be the same, right?), strip the margins, padding and bullets again, and finally, make it sit horizontally instead of vertically like it wants to. That’s what the float:left and display:block achieve.

Moving right along! We need to get that pesky text out of there, don’t we?

#navigation ul li a {
	text-indent:-9009px;
	display:block;
	height:30px;
}

So, we take it and shoot it 9009 pixels to the left. Unless someone’s on a 10,280 x 7,680 screen, that’s text is not showing up. But they’ll have other problems, too. Anyway, an important thing to note is that you cannot use <br /> tags inside those links or everything after it will still show up. text-indent only affects the first line.

Now, we are almost done. We just need to tackle the individual cells (hence the unique IDs on the <li> tags). Every <li> tag is going to have two lines in the CSS: one for the tag, and one for the link inside it.

#nav_01 {
	width:148px;
}
#nav_01 a:hover {
	width:148px;
	background:url(/images/nav_01.jpg) no-repeat 0px 0px;
}

In the first line, we declare the width of the <li> tag. We’ve already defined the heights before. This ensures that we’re filling the space of the <ul> tag. In the second line, we make sure that the link is constraining to the same width, and we set the hover property to change the background image. This is the big payoff here. When the user mouses over, instead of doing some fancy JavaScript image swap, we’re using the native CSS functionality to simply change the background to what we need. When they mouse out, the hover expires. Easy as changing the color.

So that’s it for horizontal navigation. Easy, right? But wait! you say. What about dropdowns? Dropdowns require an ID tag, which we’ve already defined. But what if you’ve got a nav parent that has no page? What if nav_02 doesn’t go anywhere? Well, that’s easy. Let’s change the construct a bit:

  <div id="navigation">
   <ul>
    <li id="nav_01"><a href="/item_1.htm" title="Top Item 1">Top Item 1</a></li>
    <li id="nav_02"><a href="/item_2.htm" title="Top Item 2">Top Item 2</a></li>
    <li id="nav_03"><a href="" title="Top Item 3" onclick="return false;">Top Item 3</a></li>
    <li id="nav_04"><a href="/item_4.htm" title="Top Item 4">Top Item 4</a></li>
    <li id="nav_05"><a href="/item_5.htm" title="Top Item 5">Top Item 5</a></li>
   </ul>
  </div>

See nav_03? We take out the URL altogether and add an onclick event. Return false; tells the browser that when the link is clicked, just don’t do anything at all. Effectively makes it a non-link. Then, we change the CSS slightly.

#nav_03 {
	width:148px;
}
#nav_03 a {
	cursor:default;
}

This tells the link to keep the same happy pointer you get for any other element that’s not a hyperlink. So now your link not only doesn’t act like a link, it doesn’t look like a link. But you keep all of your functionality (and the dropdown beneath it).

-pb

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.