Anyone who has created drop-down menus will be familiar with the large quantities of scripting such menus typically require. But, using structured
HTML and simple
CSS, it is possible to create visually appealing drop-downs that are easy to edit and update, and that work across a multitude of browsers, including Internet Explorer. Better still, for code-wary designers, no JavaScript is required! (Actually, a tiny bit of JavaScript is needed, but it’s not what you think.)
Creating the menu
The first and most important part of creating our menu is the menu structure itself. The best way to do this is to build an unordered list, with each sub-menu appearing as a list within its parent list item. Sound complicated? It’s actually very straightforward:
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a>
<ul>
<li><a href="#">History</a></li>
<li><a href="#">Team</a></li>
<li><a href="#">Offices</a></li>
</ul>
</li>
<li><a href="#">Services</a>
<ul>
<li><a href="#">Web Design</a></li>
<li><a href="#">Internet
Marketing</a></li>
<li><a href="#">Hosting</a></li>
<li><a href="#">Domain Names</a></li>
<li><a href="#">Broadband</a></li>
</ul>
</li>
<li><a href="#">Contact Us</a>
<ul>
<li><a href="#">United Kingdom</a></li>
<li><a href="#">France</a></li>
<li><a href="#">USA</a></li>
<li><a href="#">Australia</a></li>
</ul>
</li>
</ul>
That’s it: some simple
HTML that is both accessible and easy to edit.
Visually appealing?
If you have previewed the menu above, you’ll see a pretty boring list of items. And I promised you it would be visually appealing! Let’s add some style.
The first step is to remove the indents and bullets from the unordered list and define the width of our menu items.
ul {
margin: 0;
padding: 0;
list-style: none;
width: 150px;
}
Next, we need to position our list items. Fortunately, these will stack vertically by default, which is what we require. However, we must set the position as
relative
, because we will need to position the sub-menus absolutely within them.
ul li {
position: relative;
}
Next step is the sub-menus. We want each sub-menu to appear to the right of its parent menu item when that item is hovered over.
li ul {
position: absolute;
left: 149px;
top: 0;
display: none;
}
Using the “left” and “top” attributes, we can absolutely position each sub-menu within its parent menu item. You will notice I have set the “left” property to 149px (1px less than the width of the menu items), which allows the sub-menus to overlap the main menu and not produce a double border. (You’ll see what I mean later.)
We have also set display to “none,” as we don’t want the sub-menus to be visible by default.
So now we have the
framework in place, but it’s still looking a bit plain. Let’s style those links.
ul li a {
display: block;
text-decoration: none;
color: #777;
background: #fff;
padding: 5px;
border: 1px solid #ccc;
border-bottom: 0;
}
I have styled the links to my taste, but they can be changed to your preference, as you wish. It is important to set display to “block,” as we want each link to take up all the available space of its containing list item.
So things are looking a
little better, although users of Internet Explorer for Windows may disagree. Unfortunately, IE Win interprets the line breaks between our nicely formatted HTML list items as white space, so you will notice that the menu items don’t stack up neatly in that browser. However, there is a way around IE’s bugs:
/* Fix IE. Hide from IE Mac \*/
* html ul li { float: left; }
* html ul li a { height: 1%; }
/* End */
We can apply the
Holly Hack above, which hides these rules from all browsers but IE Win. Perfect. You will notice the
height: 1%
rule that has also been added. Unfortunately (again!) the float fix uncovers another IE bug, which requires a height value to make the links display as block-level elements.
You will also notice the need to close the menu, which can be done by adding the missing border to the bottom of the list. So, the
ul
rule becomes:
ul {
margin: 0;
padding: 0;
list-style: none;
width: 150px;
border-bottom: 1px solid #ccc;
}
Making it work
Now the fun bit. We need to make those sub-menus appear when we hover over the menu items.
li:hover ul { display: block; }
“Woo hoo! It works!” I hear 1% of you shout. “Awesome!”
OK, OK, so that darn IE/Win has to ruin everything and not do as it’s told. IE/Win only allows the
:hover
pseudo-class to be applied to a link — so the
li:hover
that makes the sub-menus appear means nothing to IE.
A tiny jot of JavaScript is required to kick IE back into action (line wraps marked
» —
Ed.):
startList = function() {
if (document.all&&document.getElementById) {
navRoot = document.getElementById("nav");
for (i=0; i<navRoot.childNodes.length; i++) {
node = navRoot.childNodes[i];
if (node.nodeName=="LI") {
node. {
this.className+=" over";
}
node. {
this.className=this.className.replace»
(" over", "");
}
}
}
}
}
window.οnlοad=startList;
So, the hover rule now becomes:
li:hover ul, li.over ul {
display: block; }
Additionally, we also need to associate the JavaScript with our main
ul
, which becomes:
<ul id="nav">
Hopefully, with the above tweaks in place, everyone should be able to see a simple version of the
menu in action.
IE5.01 Jumping Menu Bug
Anyone using IE5.01 on Windows will notice that the menu jumps around when you hover over some of its items. The problem is easily fixed by modifying our previous hacks as follows:
/* Fix IE. Hide from IE Mac \*/
* html ul li { float: left; height: 1%; }
* html ul li a { height: 1%; }
/* End */
Mystery IE6 Bug:
During the development of this article, I uncovered a strange bug that I believe is only apparent in IE6. A background must be declared on the li a, else when a sub-menu stretches further (vertically) than the main menu itself, the links start to disappear before you have time to click them. Strange! Try it to see for yourself.
Making it your own
That’s it! A standards-friendly method for creating visually appealing horizontal drop-down menus. All you have to do now is add some hover styles and make it your own. Just to give you a taste, here’s
a prettier one I prepared earlier. Enjoy!