HTML Guide

Lesson 9: Making a Menu

So you've got yourself a layout with some placeholder text - but then, once you start making this into a real site that's more than just one page, you'll want to create some sort of a navigation menu, usually placed vertically in one of the columns in a columned layout or sometimes horizontally across the top of the page.

The Markup

Most web developers would say that it makes the most semantic sense (remember, when we're working with the markup, we should be concerned with the semantics, the meaning of the tags we're using and how it fits with what we're using them for, not with what it will look like by default) to mark up a menu as a list, since after all it is a list of sections on the site, while usually you will negate the ordinary display of lists by setting the margins and paddings of the ul element to 0 (or whatever you prefer) and giving the ul list-style-type:none. You hopefully remember the brief discussion of lists in lesson four. To recap, an unordered list (which is what we'd use for a menu, as normally their ordering is not precisely important) is made with a ul element, with the individual list items as li elements. Lists can additionally be nested within other lists, by placing another ul element inside a li element.

A small, simple site with only a few sections that are not divided into any obvious groups will usually do fine with a simple list:

<ul>
<li><a href="home.htm">Home</a></li>
<li><a href="aboutme.htm">About Me</a></li>
<li><a href="pokemon.htm">Pokémon</a></li>
<li><a href="artwork.htm">Artwork</a></li>
</ul>

However, if you have a larger site with a large number of sections and they are divided more firmly into categories, you'll probably want to go with nested lists:

<ul>
<li>Site
<ul>
<li><a href="home.htm">Home</a></li>
<li><a href="aboutme.htm">About Me</a></li>
<li><a href="history.htm">History</a></li>
</ul>
</li>
<li>Pokémon
<ul>
<li><a href="gen1.htm">First Generation</a></li>
<li><a href="gen2.htm">Second Generation</a></li>
<li><a href="gen3.htm">Third Generation</a></li>
<li><a href="gen4.htm">Fourth Generation</a></li>
</ul>
</li>
<li>Artwork
<ul>
<li><a href="sketchbook.htm">Sketchbook</a></li>
<li><a href="gallery.htm">Gallery</a></li>
<li><a href="sprites.htm">Sprites</a></li>
</ul>
</li>
</ul>

The markup is a bit harder to follow here, but it's the sensible way to structure this menu. Sometimes you could even end up with three levels of nested lists. Note how the list item containing the name of each category - "Site", "Pokémon", "Artwork" - is also the one that contains the nested list with all the links under that category; you don't put the nested list in a new list item below, because that makes no semantic sense.

Types of Menus

Well, what kind of menu do you want? The most widely-used and practical types are these:

Simple Top Navigation
When the entire menu is placed horizontally at the top of the page. This only works for smaller menus, as a large number of links will end up cluttered. Generally this is the way to go for simple, non-nested lists like the first example above, as it takes little space, is comfortably accessible and works across all browsers.
Top Drop-Down Navigation
When the top-level menu items are arranged horizontally at the top of the page, and hovering over them causes the hidden links under that category to appear so that they can be clicked. This method can be quite nice as it allows the user to access the whole of a large menu without scrolling up or down, but its primary weaknesses are that it is more difficult to get an at-a-glance idea of what the site contains than with sidebar navigation and that actually making the drop-downs work requires either support for the :hover pseudo-class on elements other than links (which you might remember Internet Explorer 6, still in wide use, does not have) or Javascript. This is how my Axe-Murderer, Spectrum and Hellfire styles work.
Sidebar Navigation
A vertical menu like in most of my styles, going down the side of the page beside the content. Generally it would format the top-level menu items as headings. This is the most standard method of doing things, as it allows for a menu of infinite length without causing direct problems, works perfectly in all browsers and displays the whole menu on the page where the user can run their eyes over the links and see if there is anything that interests them. The main problem is that when the menu gets very big, it might become annoying for the user to find what they want, as they need to scroll up and down the menu.

If you're going to use simple top navigation or top drop-down navigation, your menu has to be placed at the top. This section assumes that you have a #menu div that contains the menu list as in the layout examples of the past two parts of this guide; regardless of where it is in the source order, it can be placed at the top of the #container (again, I'm presuming you have one) by giving it position:absolute with the top and left properties set to 0 and the width set to however wide your menu should be. To make sure the menu doesn't go on top of the content, give #content a nice padding-top.

Simple Top Navigation

If your menu is small enough to go with this, great. There are two ways to make a list horizontal. One is to give the list items display:inline to make them line up beside one another and then using padding and/or borders to separate them from one another. This works fine for simplistic displays and also has the advantage of not looking too bad even when the list breaks over multiple lines, meaning it potentially allows for a larger menu. The ul element can also be given text-align:center to easily center the menu if that's what you want. The other option, which allows you to make the menu look more fancy, is to float the ul and the list items, which just like in the columned float layout we discussed in lesson eight will line up beside one another since the containing element (the ul) is also floated. Then whatever element comes below the menu simply has to be cleared to make sure nothing gets obstructed by the menu.

Basically, for the first method you can do something like this, assuming your menu is inside a div with the id menu:

#menu ul {
text-align:center;
width:100%;
margin:0;
padding:0;
list-style-type:none;
}

#menu li {
display:inline;
}

Then you would just throw in some link styling (and possibly make the paddings on the lis). You could make it simple, like just giving the links colors and giving #menu ul a background color to make it more separated from everything else, or you could make it complicated and do a bunch of silly borders, padding, backgrounds and so on on the links to make them look like buttons or something:

#menu li a:link, #menu li a:visited {
padding:0 0.5em;
border:1px solid #FF0000;
background:#FF8888;
color:#FFFFFF;
font-weight:bold;
text-decoration:none;
}

#menu li a:hover, #menu li a:active {
background:#FFCCCC;
border-color:#FF8888;
}

Note that when there are line breaks between the list items in the HTML, the "buttons" will appear with spaces between them when you do this - if this is undesired, it can be remedied by removing the line breaks between the list items. Also note that Internet Explorer does not display top and bottom borders on inline elements; in fact, a number of things are impossible to do with inline elements, so this method is a bit limited when it comes to fancy styling of links.

For the second method, we first need to do the actual floating, which includes floating the ul left or right - it is sadly impossible to center a top menu created with the float method independently of the width of the links. We fix this, however, by giving the list items a specified width which, combined, can then be used as the width of #menu ul, making it easy to center it. (You can also use percentages for the link widths, just making sure they add up to 100%, and specify the ul's width as anything you like.) Giving the list items set widths is in fact the primary point of using the float method at all. If you attempted to do this with the inline method, you might have noticed that you couldn't; this is because you had defined the list items to be inline elements, and as briefly mentioned above, many things are not possible when dealing with inline elements. With floating, we can also make the links themselves into block-level elements using display:block, allowing us to do whatever we want with them and get as creative as we like. Since we have defined widths on the li elements, the links will not stretch across the whole screen, but only their alloted space.

#menu ul {
float:left;
margin:0 0 0 -300px;
padding:0;
list-style-type:none;
width:600px;
position:relative;
left:50%;
}

#menu li {
float:left;
width:25%;
}

#menu li a:link, #menu li a:visited {
display:block;
padding:0.2em;
background:#AAEEAA;
color:#000000;
font-weight:bold;
text-decoration:none;
}

#menu li a:hover, #menu li a:active {
background:#CCFFCC;
color:#008800;
}

Note the centering method used for #menu ul here: use position:relative to be able to shift its leftmost point to halfway across the containing element and then use a negative left margin to shift it back by half of its width. margin:auto is no use to center a floated or absolutely positioned element, but if #menu is not absolutely positioned, you could also simply give it the combined width of the list items and then center it using margin:auto. Of course, you might also just make the menu stretch across the whole screen or just want it on the left/right, removing the need to center it altogether.

Also note especially all the stuff we can do with the links when they have display:block. They can be as wide as we want, with as much padding anywhere as we want. This is also the method by which a sidebar menu can make the links reach across the whole menu and have the whole thing highlighted when hovered over.

Top Drop-Down Navigation

The basic method I use for my drop-down styles is called Suckerfish Dropdowns, a nice, standards-compliant, graceful way to create drop-downs that work in all modern browsers as long as the user has Javascript enabled if they're using Internet Explorer pre-7. I would recommend compensating for the faint possibility that the drop-downs might not work by linking the top-level menu items to portal pages containing all the links that should be in the drop-down, but that can be annoying to do; in the examples I will assume you have done this. It's up to you, I suppose.

The first thing to do once you've gotten your nested list HTML in is to do exactly the same thing with the CSS as in the floated Simple Top Navigation method. Really, exactly the same. The styling on the list items and links, however, should this time be the styling you want on the top-level menu items - the categories that you hover over.

The magic is done in a couple of simple steps. First, add position:relative to #menu li. Then add the following CSS:

#menu li ul {
display:none;
width:100%;
position:absolute;
top:100%;
left:0;
}

#menu li>ul {
top:auto;
}

#menu li:hover ul, #menu li.over ul {
display:block;
}

#menu li ul li {
float:none;
position:static;
display:inline;
}

What this does: first, it selects the nested lists and makes them disappear altogether with display:none. Here in particular, width:100% makes it exactly the same width as the parent top-level list item; you can change that if you want, in which case you might want to center the nested lists relative to their parent top-level list items by giving them left:50% and a margin-left of negative half the width. position:absolute positions it relative to the parent top-level list item and removes it otherwise from the document flow, which is what we want. top:100% and left:0 are simply there to position the drop-down correctly just below the top-level list item where we want it. The declaration for #menu li>ul is a so-called CSS hack: the direct child selector (>) between li and ul is not supported by Internet Explorer, and thus the declaration is ignored there while being parsed by other browsers. The top:auto there is just because other browsers will automatically position the drop-down correctly that way; Internet Explorer is the only one that needs top:100%. Next we have the crucial bit: the drop-downs are displayed when the parent list item is being hovered over (in standards-compliant browsers) and when it has the class over. What the Javascript does is give the list item the class over when hovered over in Internet Explorer, making it work. Finally, we need to negate the float and position declarations on #menu li ul li, and display:inline is there because of an error in Internet Explorer that causes unwanted spaces to appear between the links if this isn't done. Don't worry; the links having display:block makes them take up one line each anyway.

If you have any other properties on the top-level list items or links that you don't want on the nested ones, you'll need to negate them or change them on #menu li ul li and/or #menu li ul li a:link.

Now, all we have left is the actual script, which you can get here. Depending on your browser, you might be automatically prompted to download it or you might just be given the text; in the latter case, copy and paste it into a new file in the same folder as the site and name it dropdowns.js (or technically whatever you like, but then you have to change it below as well). If your menu does not have the id menu, you will have to change the menu in that file to your id. Then, place this line in the head of your page:

<script type="text/javascript" src="dropdowns.js"></script>

And that should be it for the drop-down menu.

Sidebar Navigation

This is the most straightforward in the CSS department. All you need to do to start with, basically, is remove the default list properties:

#menu ul {
margin:0;
padding:0;
list-style-type:none;
}

If this is all you do, your list will come out as simply one flat link in each line; then you can run with that. First, to format the category headers, you'll want to add some properties to #menu li and/or #menu li a, depending on whether the category headers are links or not (in the example they are not, but sometimes they are, depending on the needs of the website). For instance, say we want them bold and in small-caps with samplegradient.gif as a background image and some padding:

#menu li {
font-weight:bold;
font-variant:small-caps;
background:url('samplegradient.gif') repeat-x #DDDDFF;
padding:0.1em 0.5em;
}

That's all fine and dandy, but if we just put this on, these properties will also apply to the second-level list items, which they presumably shouldn't. Thus, we need to cancel them out there:

#menu li ul li {
font-weight:normal;
font-variant:normal;
background:transparent;
padding:0;
}

It is worth noting that since the nested lists are inside lis, the paddings will also move the edges of the nested lists and the background will show behind them. If this is undesired, you can either add another background on #menu li ul to block out the background on #menu li, use block-level links in the nested lists and give them background colors that block it out, or you can wrap another element around the category headings (such as if they are links) and apply the original styling to those elements instead.

Now, we can go two ways with the links. If you want them to stay inline (so that the user needs to click the actual link to get anywhere), you might want to add some paddings, borders and/or backgrounds to #menu li ul li and then use standard link styling. If, on the other hand, you want the links to take up the entire horizontal space they have so that you can change the background color of an entire strip when a link is hovered over, you first need to give the links display:block, and in that case, it will again be necessary to give #menu li ul li display:inline to prevent unwanted gaps from appearing between the links in Internet Explorer. Then you can give the links paddings like any other block-level element.

You can see a sample with all the menu types discussed in this lesson here. Look at the source (View > Source or View > Page Source in most browsers as far as I know) of that to see exactly how each one was achieved if you're not sure.

Previous lesson - Next lesson

Page last modified August 13 2016 at 02:34 UTC