Multi-Level Menus

The first thing to do when you want to add a multi-level navigation menu to your web page is to define the HTML. Since a menu is a list of links that's the appropriate way to define it. Since here we are just concerned with the operation of the menu itself we'll leave out the links so that we can see more clearly how the multi-level lists need to be nested inside one another.

<ul id="nav">
<li>entry 1
    <ul><li>entry 1a</li>
    <li>entry 1b</li>
    </ul></li>
<li>entry 2
    <ul><li>entry 2a</li>
    <li>entry 2b</li>
    </ul></li>
</ul>

Your menu almost certainly will have a different number of entries in each level of the menu but these are enough to illustrate how the HTML wraps around the menu entries. Note that the nested list for the sub-menu must be contained within the same <li> tag as the entry in the higher level menu it is attached to. You can make all the text in the menu into links simply by wrapping thetext inside an <a> tag. If you want people to be able to work the links in the menu by clicking anywhere on the menu then apply display:block and the same width as you used for the li tags to them.

The next thing to decide is whether you want your top level menu to be horizontal or vertical. The CSS for both is almost the same. We'll start with that for a horizontal menu.

#nav, #nav ul, #nav li {padding:0; margin:0;}
#nav {display:block; text-align:center}
#nav li { float: left; width: 9em; position:relative; height:1.3em;
border: 1px solid #000; list-style: none;}
#nav li ul {position: absolute; width: 9em; left: -100em; top: 1.3em;
list-style: none;}
#nav li:hover ul {left: 0;}

The parts that make the menu work are the float:left on the li tags that allows them to go on the same line for our horizontal menu. We need position:relative on that element in order to be able to position the sub-menu relative to its heading entry in the main menu. The width and height make all our menu entries the same size, they don't have to be 9em and 1.3em but if you change them you need to change all the references in this code. The sub-menu will be displayed in one of two positions with top:1.3em setting down below the content of its parent which has that as its height.. When the mouse isn't over its parent the sub-menu is positioned left:-100em which puts it well and truly off the left edge of the web page. When the mouse hovers over the parent element the left:0 moves it back under that parent element so the sub-menu appears. As the sub-menu is nested inside the heading the mouse is still hovering over the same li tag when you move it into the sub-menu.

Here's the menu with the top level displayed vertically instead of horizontally.

#nav, #nav ul, #nav li {padding:0; margin:0;}
#nav {display:block; text-align:center; width:9em;}
#nav li { float: left; width: 9em; position:relative; height:1.3em;
border: 1px solid #000; list-style: none;}
#nav li ul {position: absolute; width: 9em; left: -100em; top: 0;
list-style: none;}
#nav li:hover ul {left: 9em;}

The changes from the horizontal version are: the width on the outer ul tag, the top of the sub-menu is now zero instead of the height of its parent, and the left position when the mouse hovers over the parent is now the same as the width of the parent so that it now displays to the right of its parent instead of below it.

This sample page demonstrates both the horizontal and verticle menus. Note that the second menu is wrapped in a div simply to allow the positioning of that div that moves it away from the other menu to be kept separate from the code for the menu itself.

We may of course want more than two levels in our menu in which case we just add the extra lists into the HTML in the same way we did with the second level. The CSS is slightly more complicated because we need to distinguish which level is being hovered on. The following CSS will work with adding a third level to either of the above menus (since the third level will need to go next to the second.

#nav li ul ul, #nav li:hover ul ul {position: absolute; width: 9em;
left: -100em; top: 0; list-style: none;}
#nav li li:hover ul {left: 9em;}

 

This article written by Stephen Chapman, Felgall Pty Ltd.

go to top

FaceBook Follow
Twitter Follow
Donate