Watch our 3-minute video to find out how you can learn CSS with a live instructor.
Additional Resources

CSS Lists as Hierarchical Navigation

In this lesson of the CSS tutorial, you will learn...
  1. To use lists as vertical navigation.
  2. To use nested lists for multi-level navigation.
  3. To use lists as horizontal navigation.
  4. To use lists as drop-down navigation.

Navigation bars or menus present a list of choices to the visitor. For example,

  • Home
  • Services
  • Products
  • Support
  • Blog
  • About
  • Contact

Often these choices will have nested options. For example, under About, you might find:

  • Company History
  • Our Staff
  • Press Releases
  • Investor Information

In this lesson of the CSS tutorial, you'll learn how to properly mark up these menus using HTML lists and to use CSS to style them.

Menus as Lists

Let's start by marking up the first list shown above as HTML and giving the list an id of "mainMenu":

<ul id="mainMenu">
 <li><a href="home.html">Home</a></li>
 <li><a href="services.html">Services</a></li>
 <li><a href="products.html">Products</a></li>
 <li><a href="support.html">Support</a></li>
 <li><a href="blog.html">Blog</a></li>
 <li><a href="about.html">About</a></li>
 <li><a href="contact.html">Contact</a></li>
</ul>

With no CSS, this menu will display as follows:

Let's now see how we can turn the list into a stylish navigation menu.

CSS Horizontal Menu

First, we'll create a horizontal menu that looks like this: We will follow these steps:

  1. Remove all the default list styling. We can do this using Eric Meyer's reset CSS, which contains the following rule:
    ol, ul {
     list-style: none;
    }
  2. Set the width and margin of the menu.
    #mainMenu {
     margin:10px;
     width:900px;
     font-family: "Trebuchet MS";
    }
    Setting the width prevents the menu from wrapping when the user shrinks the browser window.
  3. Set the list items to display as blocks. We'll also give them a width, float them to the left so that they'll each come up to the right of the preceding item, and give them a margin border.
    #mainMenu li {
     display:block;
     width:120px;
     float:left;
     margin-left:2px;
     border:1px solid #000;
    }
  4. Change the a elements to block-level elements. We'll also add some formatting styles and remove the underline with text-decoration:none.
    #mainMenu a {
     display:block;
     padding:3px;
     text-decoration:none;
     background-color:#fff;
     color:#009;
    }
  5. Finally, we change the hover state of the links so that they highlight when a user points to them:
    #mainMenu a:hover {
     background-color:#009;
     color:#fff;
    }

That's it. The full CSS code is shown below:

Code Sample: CssListMenus/Demos/CssMenu-horizontal.html

---- Code Omitted ----
<link type="text/css" rel="stylesheet" href="../reset-meyer.css" /> <style type="text/css"> #mainMenu { margin:10px; width:900px; font-family: "Trebuchet MS"; } #mainMenu li { display:block; width:120px; float:left; margin-left:2px; border:1px solid #000; } #mainMenu a { display:block; padding:3px; text-decoration:none; background-color:#fff; color:#009; } #mainMenu a:hover { background-color:#009; color:#fff; } </style>
---- Code Omitted ----
Code Explanation

Open CssListMenus/Demos/CssMenu-horizontal.html in your browser to see it in action.

CSS Vertical Menu

Vertical menus are created in much the same way, but they're even easier. The steps below show how to create a menu that looks like this:

  1. Remove all the default list styling. Again we use Eric Meyer's reset CSS.
  2. Set the width and margin of the menu. This time will make the menu much narrower as we're creating a vertical menu:
    #mainMenu {
     margin:10px;
     width:120px;
     font-family: "Trebuchet MS";
    }
  3. Set the list items to display as blocks. We'll also set the border properties adding borders to the left, right and bottom edges and then adding a border to the top of only the first list item. We use the :first-child pseudo-class (see footnote) to do this.
    #mainMenu li {
     display:block;
     border:1px solid #000;
     border-top:0px;
    }
    #mainMenu li:first-child {
     border-top:1px solid #000;
    }
  4. Change the a elements to block-level elements. Again, we'll also add formatting styles and remove the underline with text-decoration:none.
    #mainMenu a {
     display:block;
     padding:3px;
     text-decoration:none;
     color:#009;
    }
    
  5. Finally, we change the hover state of the links so that they highlight when a user points to them:
    #mainMenu a:hover {
     background-color:#009;
     color:#fff;
    }

The full CSS code is shown below:

Code Sample: CssListMenus/Demos/CssMenu-vertical.html

---- Code Omitted ----
<link type="text/css" rel="stylesheet" href="../reset-meyer.css" /> <style type="text/css"> #mainMenu { margin:10px; width:120px; font-family: "Trebuchet MS"; } #mainMenu li { display:block; border:1px solid #000; border-top:0px; } #mainMenu li:first-child { border-top:1px solid #000; } #mainMenu a { display:block; padding:3px; text-decoration:none; color:#009; } #mainMenu a:hover { background-color:#009; color:#fff; } </style>
---- Code Omitted ----
Code Explanation

Open CssListMenus/Demos/CssMenu-vertical.html in your browser to see it in action.

CSS Dynamic Menus

Dynamic menus have long been popular on the web. Until relatively recently, it was necessary to use JavaScript to create these menus. The wider support of the :hover pseudo-class changes that. In this section, we'll show you how to create dynamic menus using pure CSS.

The dynamic menus shown in this lesson will not work in Internet Explorer 6 and earlier. To create expanding menus for IE 6 and earlier, you will most likely (see footnote) have to use JavaScript.

CSS Dropdown Menu

So far, we have only looked at how we can use CSS to change the display of single-level menus. But what happens when we introduce a second level of choices using a nested list. The code sample below shows the same horizontal menu we saw before, but with the addition of a nested list:

Code Sample: CssListMenus/Demos/CssMenu-horizontal-nested.html

---- Code Omitted ----
<ul id="mainMenu"> <li><a href="home.html">Home</a></li> <li><a href="services.html">Services</a></li> <li><a href="products.html">Products</a></li> <li><a href="support.html">Support</a></li> <li><a href="blog.html">Blog</a></li> <li><a href="about.html">About</a> <ul> <li><a href="history.html">Company History</a></li> <li><a href="staff.html">Our Staff</a></li> <li><a href="press.html">Press Releases</a></li> <li><a href="investorInfo.html">Investor Information</a></li> </ul> </li> <li><a href="contact.html">Contact</a></li> </ul>
---- Code Omitted ----
Code Explanation

With this nested list in place and without changing the CSS, this page will display as follows:

By modifying the CSS, we can hide the submenus until the user hovers over one of the parent menu items. Here are the steps:

  1. Set the position of the main menu items to relative. We will need to position the submenus using absolute positioning, but absolutely positioned elements are positioned within their nearest non-statically positioned containing element. So, to prepare for that, we'll first make the main list items relatively positioned:
    #mainMenu li {
     position:relative;
     /*other declarations omitted*/
    }
  2. Position the submenus absolutely. Submenus are contained in ul elements within li elements. The following rule uses absolute positioning to position them immediately below those li elements:
    #mainMenu li ul {
     position:absolute;
     margin:0px;
     padding:0px;
     left:-3px;
     top:22px;
    }
    The result:
  3. Hide the submenus. Add display:none; to the rule above to hide the submenus.
  4. Style the submenu options. The two rules below add borders around the submenu options. We turn the top border off for all but the first option, which we identify with the :first-class pseudo-class so that we don't get a double-thick border resulting from top and bottom borders of adjacent options.
    #mainMenu li ul li {
     width:150px;
     font-size:smaller;
     border-top:none;
    }
    #mainMenu li ul li:first-child {
     border-top:1px solid #000;
    }
  5. Display the submenu when the user hovers over the main option. Modern browsers allow the :hover pseudo-class for almost all elements, including list items. The code below sets the display property of the submenu to block when the user hovers over the parent list item:
    #mainMenu li:hover ul {
     display:block; 
    }

That's it. The full CSS code is shown below:

Code Sample: CssListMenus/Demos/CssMenu-dropdown.html

---- Code Omitted ----
<link type="text/css" rel="stylesheet" href="../reset-meyer.css" /> <style type="text/css"> #mainMenu { margin:10px; width:900px; font-family: "Trebuchet MS"; } #mainMenu li { position:relative; display:block; width:120px; float:left; margin-left:2px; border:1px solid #000; } #mainMenu a { display:block; padding:3px; text-decoration:none; background-color:#fff; color:#009; } #mainMenu a:hover { background-color:#009; color:#fff; } #mainMenu li ul { position:absolute; margin:0px; padding:0px; left:-3px; top:22px; display:none; } #mainMenu li ul li { width:150px; font-size:smaller; border-top:none; } #mainMenu li ul li:first-child { border-top:1px solid #000; } #mainMenu li:hover ul { display:block; } </style>
---- Code Omitted ----
Code Explanation

Open CssListMenus/Demos/CssMenu-dropdown.html in your browser to see it in action.

CSS Flyout Menu

Let's now take a look at creating a flyout menu, which is very similar to creating a dropdown menu. The code sample below shows the vertical menu we saw before, but with the addition of several nested lists:

Code Sample: CssListMenus/Demos/CssMenu-vertical-nested.html

---- Code Omitted ----
<ul id="mainMenu"> <li><a href="home.html">Home</a></li> <li><a href="services.html">Services</a> <ul> <li><a href="service1.html">Service 1</a></li> <li><a href="service2.html">Service 2</a></li> <li><a href="service3.html">Service 3</a></li> </ul> </li> <li><a href="products.html">Products</a> <ul> <li><a href="product1.html">Product 1</a></li> <li><a href="product2.html">Product 2</a></li> <li><a href="product3.html">Product 3</a></li> </ul> </li> <li><a href="support.html">Support</a></li> <li><a href="blog.html">Blog</a></li> <li><a href="about.html">About</a> <ul> <li><a href="history.html">Company History</a></li> <li><a href="staff.html">Our Staff</a></li> <li><a href="press.html">Press Releases</a></li> <li><a href="investorInfo.html">Investor Information</a></li> </ul> </li> <li><a href="contact.html">Contact</a></li> </ul>
---- Code Omitted ----
Code Explanation

With this nested list in place and without changing the CSS, this page will display as follows:

By modifying the CSS, we can move the submenus over to the right and hide tehm until the user hovers over one of the parent menu items. Here are the steps:

  1. Set the position of the main menu items to relative. Like with dropdown menus, we will need to position the submenus using absolute positioning:
    #mainMenu li {
     position:relative;
     /*other declarations omitted*/
    }
  2. Position the submenus absolutely and hide the submenus.
    #mainMenu li ul {
     position:absolute;
     width:150px;
     left:118px;
     top:5px;
     display:none;
    }
  3. Style the submenu options.
    #mainMenu li ul li {
     font-size:smaller;
    }
  4. Display the submenu when the user hovers over the main option. The background-color declaration is necessary for Internet Explorer 7. Without it, the submenus can disappear while the user is hovering over them.
    #mainMenu li:hover ul {
     display:block;
     background-color:#fff; /*for IE7*/
    }
  5. Position a tags relatively. This is another fix for Internet Explorer 7. If the a tags are left statically positioned, then they won't fill the full width of their parent list items and the menus will only work when users hover over the text of the link.
    #mainMenu a {
     position:relative; /*for IE7*/
     /*other declarations omitted*/
    }

Exercise: Combining Dropdown and Flyout Menus

Duration: 20 to 30 minutes.

In this exercise, you'll modify a working dropdown menu so that third-level options will flyout to the right as shown in the screenshot below:

  1. Open CssListMenus/Exercises/CssMenu-mixed.html in your browser.
    1. Hover over the About menu. You should see this:
    2. Notice the third-level menu. It is currently not functional.
  2. Open CssListMenus/Exercises/CssMenu-mixed.html in your editor.
  3. Change the CSS so that the third-level menu is functional and flies out to the right.

The full code is shown below:

Code Sample: CssListMenus/Demos/CssMenu-flyout.html

---- Code Omitted ----
<link type="text/css" rel="stylesheet" href="../reset-meyer.css" /> <style type="text/css"> #mainMenu { margin:10px; width:120px; font-family: "Trebuchet MS"; } #mainMenu li { position:relative; display:block; border:1px solid #000; border-top:0px; } #mainMenu li:first-child { border-top:1px solid #000; } #mainMenu a { position:relative; /*for IE7*/ display:block; padding:3px; text-decoration:none; color:#009; } #mainMenu a:hover { background-color:#009; color:#fff; } #mainMenu li ul { position:absolute; width:150px; left:118px; top:5px; display:none; } #mainMenu li ul li { font-size:smaller; } #mainMenu li:hover ul { display:block; } </style>
---- Code Omitted ----
Code Explanation

Open CssListMenus/Demos/CssMenu-flyout.html in your browser to see it in action.

  1. In the HTML, you'll notice the "Corporate Governance" bullet has a submenu that is commented out. Uncomment it.
  2. Modify your CSS so that this new submenu is also function and flies out when the user hovers over "Corporate Governance", but not before:
  3. Hint: you will only need to change one character.

Accessibility

Navigation menus marked up as lists are much more accessible than menus marked up in tables or nested divs. One way to get a feel for this is to turn off CSS in the browser to see if the menu is still navigable. In Firefox, you can do this by choosing View > Page Style > No Style from the main menu. When we look at CssListMenus/Solutions/CssMenu-mixed-challenge.html in this view, here's what we see:

This is how a screen reader might "see" the page. Because of the logical structure, it should have no problem presenting it correctly.

CSS Lists as Hierarchical Navigation Conclusion

In this lesson of the CSS tutorial, you have learned to use lists for accesible static and dynamic navigation menus.

Footnotes

  1. For browsers such as Internet Explorer 6 that don't support the :first-child pseudo-class, you can add a "first" class to the first list item and apply the style to the #mainMenu li.first selector.

  2. Stu Nichols has succeeded in creating a dropdown menu that works in Internet Explorer 6 without using JavaScript. See http://www.cssplay.co.uk/menus/final_drop.html. His solution, which is copyrighted, makes heavy use of CSS hacks and Internet Explorer conditional comments.

To continue to learn CSS go to the top of this page and click on the next lesson in this CSS Tutorial's Table of Contents.
Last updated on 2009-10-16

Use of http://www.learn-css-tutorial.com (Website) implies agreement to the following:

Copyright Information

All pages and graphics on Website are the property of Webucator, Inc. unless otherwise specified.

None of the content on Website may be redistributed or reproduced in any way, shape, or form without written permission from Webucator, Inc.

No Printing or saving of pages or content on Website

This content may not be printed or saved. It is for online use only.


Linking to Website

You may link to any of the pages on Website; however, you may not include the content in a frame or iframe without written permission from Webucator, Inc.


Warranties

Website is provided without warranty of any kind. There are no guarantees that use of the site will not be subject to interruptions. All direct or indirect risk related to use of the site is borne entirely by the user. All code and explanations provided on this site are provided without warranties to correctness, performance, fitness, merchantability, and/or any other warranty (whether expressed or implied).


For individual private use only

You agree not to use this online manual to deliver or receive training. If you are delivering or attending a class that is making use of this online manual, you are in violation of our terms of service. Please report any abuse to courseware@webucator.com. If you would like to deliver or receive training using this manual, please fill out the form at http://www.webucator.com/Contact.cfm