Vertical Navigation with Pop Out Menus


Click on the movie reel icon to view a video demonstration. You may need to watch the video a few times to totally understand the concepts. Feel free to print out the notes and copy the code from the files which are linked at the bottom of the page.

Before we begin the lesson I would like to thank Nick Rigby author at A List Apart http://www.alistapart.com/articles/horizdropdowns/

In this demonstration we will learn how to create a vertical column of buttons, which displays pop out menus when you hover.

Here is how the page looks when I begin

Here is the finished vertical column of buttons

Let's begin with a basic HTML page which has basic tags and a group of nested lists. The outer list is displayed in bold and the 3 inner lists are displayed in italic.

original HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Vertical Pop Out List</title>
</head>
<body>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Family</a>
<ul>
<li><a href="#">John</a></li>
<li><a href="#">Jenny</a></li>
<li><a href="#">Jessica</a></li>
</ul>

</li>
<li><a href="#">Pets</a>
<ul>
<li><a href="#">Lightening</a></li>
<li><a href="#">Maverick</a></li>
<li><a href="#">Goldfish</a></li>
<li><a href="#">Aquarium Fish</a></li>
</ul>

</li>
<li><a href="#">Contact Me</a>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Office</a></li>
</ul>

</li>
</ul>

</body>
</html>

The key issue is how you nest one list inside another. The inner list is part of a list item from the outer list. In the example below the list item contains a link for the word "Family" and the inner list that displays John, Jenny and Jessica.

<li><a href="#">Family</a>
<ul>
<li><a href="#">John</a></li>
<li><a href="#">Jenny</a></li>
<li><a href="#">Jessica</a></li>
</ul>

</li>

Here is the page displaying nested lists

Now let's add some CSS to the head of the document which controls the unordered list. This code removes the list indentation and bullets while setting the width of the column to 150 pixels.

<style type="text/css">

ul {
margin: 0;
padding: 0;
list-style: none;
width: 150px;
}

</style>

Here is the navigation column at this stage of the lesson. The main list and sub lists all display in a column. I also notice that the indentation and bullets have been removed.

I return to the code and add 2 more styles.

<style type="text/css">
ul {
margin: 0;
padding: 0;
list-style: none;
width: 150px;
}

ul li {
position: relative;
}

li ul {
position: absolute;
left: 149px;
top: 0;
display: none;
}

</style>

The first style is for an unordered list tag that will have a position of relative.

The next style applies only to an unordered list which is nested within a list item (li ul). Once the browser encounters this series of tags it sets the position of the list to an absolute value of 149 from the left. That value of 149 is intentionally set to 1 pixel less than the outer list so that the pop out menu will sit on the last pixel of the main menu. If the position of the inner list had been 150 pixels, the border of the 2 lists would have displayed as a double line and that would be awkward.

The final declaration sets the inner list to a display value of none, which hides those lists.

Here is the page with the inner lists hidden

Now let's add another style which will control the a tag within a list item. This style will control <a> tags within the outer and inner lists.

<style type="text/css">
ul {
margin: 0;
padding: 0;
list-style: none;
width: 150px;
}

ul li {
position: relative;
}

li ul {
position: absolute;
left: 149px;
top: 0;
display: none;
}

ul li a {
display: block;
text-decoration: none;
color: #eee;
background: #abc287;
padding: 5px;
border: 1px solid #8ea867;
border-bottom: 0;
}

</style>

This code does several things, first the a tag is traditionally an inline element, by adding display:block the browser will treat the link like a block element. This makes the entire area of the list item as a hot, clickable area. In a traditional link within a list, only the linked text is hot. I am trying to create a column of clickable buttons which are made up of list items and this display property is essential. Next I remove underline from the links, set the link color to light gray, and set the background color to green.

Then I add 5 pixels of padding to all 4 sides of the link while adding a 1 pixel border in dark green. Finally I remove the bottom border from the list items. If I kept the bottom border I would have a double line between the list items. Now when I view the page it displays a column of buttons.

After viewing the page in the browser I see a green column of buttons with white text. Each list item is outlined in a dark green border. I am missing a bottom border on the last button, but that is easy to fix.

I return to the code and modify the style for an unordered list by adding a bottom border. That will place a line below my last list item. Finally I add a declaration that asks the browser to display the inner list when I hover over the outer list item. I also include a comment so I am reminded of the importance of this declaration.

<style type="text/css">
ul {
margin: 0;
padding: 0;
list-style: none;
width: 150px;
border-bottom:1px solid #8ea867;
}

ul li {
position: relative;
}

li ul {
position: absolute;
left: 149px;
top: 0;
display: none;
}

ul li a {
display: block;
text-decoration: none;
color: #eee;
background: #abc287;
padding: 5px;
border: 1px solid #8ea867;
border-bottom: 0;
}

/* causes sub menu to display when I hover over main menu */
li:hover ul { display: block; }

</style>

Let's view the page now that I can see my inner lists. When i hover over the main list items an inner list displays. I also see that I now have a line at the bottom of my list. In the next 2 lessons I will learn how to add hacks so this code will work with IE and then I will modify the look of the lists.

View page that displays inner lists when we hover