Over a million developers have joined DZone.

HTML and CSS List Based Menus

· Web Dev Zone

Start coding today to experience the powerful engine that drives data application’s development, brought to you in partnership with Qlik.

HTML and CSS based menus is nothing new. I believe web developers has understood the semantic meaning behind this and are using lists to create their web site menu structures. With that said, what does lists add in a semantic sense. If you think about a menu of a website, what does it boil down to? A list of links that gives a user access to the various sections of a web site. The keyword here is a list. So, this is where lists gives menus and other collections of links added semantic meaning.


HTML And CSS List Based Menus from Schalk Neethling on Vimeo.

Download Screencast For Offline Viewing

Now HTML offers us two types of lists, unordered and ordered lists and I believe that we should use both for our navigation but, where appropriate. What do I mean by that? That is what this article is about. Not only will I demonstrate how to create accessible, standards based menu's using HTML and CSS but I will also show why I think unordered lists is not the best solutions for every situation and why sometimes an ordered list makes more semantic sense. With that, let's start be creating a horizontal menu using HTML and CSS.

So our first point of call is creating the semantic structure of our menu.

<ul>
<li>Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>

Next we need to link each of our individual items.

<ul id="nav">
<li><a href="index.html" title="return to front page">Home</a></li>
<li><a href="about.html" title="learn more about us">About</a></li>
<li><a href="portfolio.html" title="see some samples of our work">Portfolio</a></li>
<li><a href="contact.html" title="contact us">Contact</a></li>
</ul>

You will notice that I have used the title attribute on every link, while these links may give a clear indication of what a users can expect to find once they follow the link, it may not always be the case. Examples include links that uses the text 'read more', when images are used as links etc. The first practice of using 'read more' as link text is strongly discouraged by the W3C and does not do much from an SEO perspective however, it is still done by some. If you find 'read more' or something similar to be the most appropriate, please use the title attribute to tell the users what they can expect once they follow the link. Next we have to turn the above into a horizontal menu. This is where CSS comes into play.

body
{
background-color:#fff;
color:#000;
font:.9em/1.2em Arial, Helvetica, sans-serif;
}

The above sets some defaults up for our document as a whole. In this case we are setting our background color to white and our foreground color i.e. font color, to black. I also use the CSS font short-hand to specify the default font size, the line-height and the font family. Before we go any further assure that you have linked up your stylesheet in the head of your HTML document as such:

<link rel="stylesheet" type="text/css" href="css/default.css" media="screen" />

If your are using a HTML 4.0+ doctype drop off the / at the end of the above line. The type attribute of the above link tag is not optional ans has to be included. One of the attributes I have added here, but that is optional, is the media attribute. While this is optional, once you start to work with print style sheets and style sheets aimed at mobile and other devices you will come to appreciated this attribute, so I suggest start using it today. The above attribute simply tells the device that this style sheet is meant to be applied to the document if the document is displayed on screen.

Now in order to ensure the styles that we write for our menu will only be applied to our navigation HTML list we have to find a way to identify or directly target it. Now seeing that in general you will have your menu only occur once one your page we can safely use an id to target our list however, if you will be duplicating the menu on the same page then you should use a class instead. Either way you go we need to change the HTML slightly:

<ul id="nav">

Now that we can target our list our first step is to remove all margins and padding from the list as well as the bullets that appear to the left of our list items. We do this as follows:

#nav, #nav ul
{
background-color:#fff;
color:#000;
margin:0;
padding:0;
list-style:none;
}

With that done, go ahead and open it in a browser. You will see that not much is different from a usual list other then the obvious, no margin or padding and no bullets. As we want to end up with a horizontal menu we need to tell the list items not to follow their ussual behaviour of stacking vertically but that they should float next to each other. Ah float, now CSS does provide us with such a style rule. Add the following to your CSS file to target the individual list items and get them to break their usual habit:

#nav li
{
background-color:#fff;
color:#000;
float:left;
}

If you refresh the previous page in your browser now you will see that the float rule has indeed forced our items to float next to each other however, they are definitely fighting for space. To give each list item a little breathing space add the following to the above rule block.

padding:10px;

Go ahead and refresh the page again. Now the links have a nice amount of space around them but it is still not styled enough like a menu you would use on your website. On of the things we can add is some background color to differentiate it. To do this we will be targeting the anchor link as follows:

#nav li a
{
background-color:#6A9F00;
display:block;
padding:10px;
}

When you refresh the page now, you will see that the links have changed to now have a green background color. There are a couple of other things to notice here. First, we surely do not want all that additional space around our individual menu items, although we might want to keep a little spacing on the side of each to clearly separate them. Change the #nav li rule as follows:

#nav li
{
background-color:#fff;
color:#000;
float:left;
padding:0 1px 0 0;
}

With this fixed you next notice that the font color of the links just is not working. But you will also notice that the link to 'Home' is a purple color while the other three is in blue. One of the reasons is that we have not changed the color of our font for links. Also, there are two different initial states we need to target for our links:

#nav li a:link, #nav li a:visited
{
background-color:#6A9F00;
color:#fff;
display:block;
padding:10px;
}

Normally when dealing with text links it is best to leave the underline there as a visual cue to the user that the piece of text is in fact a link. However, as we are dealing with a menu it is already obvious that these items are links so why not go ahead and get rid of the underline under our text items. To do this add the following line to the previous rule block:

text-decoration:none;

Great, so now we have a simple HTML menu that you can use on your website. However, currently there is no interactivity, so let's add a little hover action. To do this we will be targeting the, you guessed it, hover state of the anchor tag. Here we will change the background color to a lighter shade of green and also changing the font color to black.

#nav li a:hover
{
background-color:#99CE71;
color:#000;
}

We do not need to add anything else to the hover rule block as the rest will be inherited by the magic of the CSS cascade. So there you go, we have a usable menu you can easily customize for your needs on your own website. Next we will look how to turn this menu into a vertical menu as apposed to a horizontal menu. To do this is so simple it almost seems criminal. First we remove the float rule from the #nav li block leaving the following:

#nav li
{
background-color:#fff;
color:#000;
padding:0 1px 0 0;
}

Refresh your page and there it is. We have basically turned our horizontal menu into a vertical menu by removing one line. Another small thing we should change is that at the moment we have a 1px right margin. We should really change this to a bottom margin so, change the padding for #nav li as follows:

padding:0 0 1px 0;

With that done we are there. The one thing you will notice currently is that the menu will just stretch to fill the available area. When placed into a container that has a set width it will obviously only expand to fill this area. However, if you want to keep the HTML as is and not introduce a DIV or something along those lines, you can control the width of the menu by setting a fixed width on the ul. So to do this add a width attribute to the #nav ul rule:

#nav, #nav ul
{
background-color:#fff;
color:#000;
margin:0;
padding:0;
width:15em;
list-style:none;
}

You will notice that I used em as a unit of measure as apposed to the ussual pixel. The reason for this is to allow the background to increase in width and height as the user increases their chosen font size. When developing websites and you do not need pixel perfect positioning and control, it is definitely the unit of measure of choice. Now our good friend IE6 will more then likely throw us a huge cureveball here by not giving us any height to work with. This is the old has-layout bug with IE6. Tofix this add the following to your ul:

height:1%;

I hinted at the start of this article that I was also going to touch on when it might make more semantic sense to use an ordered list for navigation as apposed to an unordered list. An unordered list is just exactly that unordered. So whenever you are marking up a list of links that forms part of something such as a wizard or any other collection of links that has a definite structure it makes a lot more sense to me to use an ordered list to mark-up your links then an unordered list.

The additional benefit you get from this is that you do not have to add arbitrary text such as 1., 2. to your HTML and screen readers will also make it clear that the links has a specific order that needs to be followed. So let's look at our first horizontal menu and turn it into a ordered list menu. First thing we have to do is change our HTML slightly as follows:

<ol id="nav">
<li><a href="index.html" title="Enter your presonal information">Personal Info</a></li>
<li><a href="about.html" title="Enter your residential information">Residential Info</a></li>
<li><a href="portfolio.html" title="Fill ot your work history">Work History</a></li>
<li><a href="contact.html" title="Complete our skills matrix">Skills Matrix</a></li>
</ol>

Next we need to change our CSS as follows:

#nav, #nav ol
{
background-color:#fff;
color:#000;
margin:0;
padding:0;
height:1%;
overflow:auto;
}

You will notice that I also added the overflow attribute here. The reason for this is simply to allow the background color of the the ordered list to fill the entire height of the contained list items and not be hidden. Next step is to change out #nav li rule to fix up the problems that are occurring with our list numbers to the left.

#nav li
{
background-color:#8fbbbf;
color:#fff;
margin-left:27px;
float:left;
}

So here we have given the list elements the same new background color as we did for the ordered list itself. Next we removed the previous padding and replaced it with a single left margin of 27 pixels. For the links the only thing we are going to change is adding a 1 pixel border on all sides of our navigation elements. I also changed the background color to create a more aesthetically pleasing effect:

#nav li a:link, #nav li a:visited
{
background-color:#475D5F;
color:#fff;
display:block;
padding:5px;
border:1px solid #fff;
text-decoration:none;
}

For the hover state I did two things. First I changed it's background color to be the same as that of the ordered list and added the focus state. This means the if we tab over the list the background will also change when the element receives focus not just when the mouse pointer is hovered over the element. So we end with this:

#nav li a:hover, #nav li a:focus
{
background-color:#8fbbbf;
color:#000;
}

There you go! Combine this with some unobtrusive JavaScript to load different 'pages' based on which element is clicked and you have a great looking wizard menu with added semantic value. With a few simple tweaks you can change the feel of this to buttons that seems to be set into the page to something quite different. Simply do the following, add 5px of padding to your ordered list:

#nav, #nav ol
{
background-color:#fff;
color:#000;
margin:0;
padding:5px;
height:1%;
overflow:auto;
}

And then ensure that your hover and focus states has the same border color as the background of the ordered list:

#nav li a:hover, #nav li a:focus
{
background-color:#8fbbbf;
color:#000;
border:1px solid #8fbbbf;
}

That is then my coverage of creating basic menu structures using only HTML and CSS and why it sometimes makes more semantic sense to use an ordered list as apposed to a unordered list to mark-up your menus. I hope you enjoyed this article and can take something away. Please feel free to add your comments below and offer your suggestions or counter arguments if you don't agree with my thoughts here.

Create data driven applications in Qlik’s free and easy to use coding environment, brought to you in partnership with Qlik.

Topics:

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}