Pure CSS Vertical Menu
Today we are going to build the second most common site menu navigation, the vertical navigation menu. Here we are going to be using only pure CSS and unordered lists to create our vertical navigation menu with three levels of pop outs. This version of the vertical navigation menu will work in IE5, IE6, IE7 and IE8 as well as FF and Safari.
Let’s begin shall we. To start lets create our menus container block and give it an id of “navigation”.
<div id="navigation"> </div>
Next we will add our first level menu items.
<div id="navigation">
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
After this we are going to give our list items some names.
<div id="navigation">
<ul>
<li>Home</li>
<li>About</li>
<li>Contact</li>
<li>FAQ</li>
<li>News</li>
</ul>
</div>
Great let’s see what we have so far.
Obviously it’s not going to work for us, but I think it’s important to point out that the vertical fashion that is given to us by default in the ordered list is here to help us. The vertical menu and unordered list almost seems to be a match made in CSS heaven vs. its sister menu the horizontal navigation menu.
So let begin to add some style to our first level unordered list and its parent container “navigation” shall we.
In our header we create some style tags that will contain all our CSS. Our first CSS rule we want to add would be for our container.
<style type="text/css">
#navigation {width:150px; font-size:12px;}
</style>
Here we are going to give our main container some structure by setting its width to 150 pixels; we also set our menus font size to that of 12 pixels that will cascade down our entire menu.
Great next we are going to create a rule for our first level unordered list.
<style type="text/css">
#navigation {width:150px; font-size:12px;}
#navigation ul {margin:0px; padding:0px; background-color:#666;}
</style>
Ok here we are pointing to our “navigation” container first, then our first unordered list and assigning styles accordingly. We have removed the default margin and padding that comes with a unordered list by setting both to 0 pixels. For style sakes we set our first unordered list’s background color to # 666.
Ok let’s see what we have so far.
Again not looking to hot right now, but we will get there. Our next step is to assign some styles to our unordered list items. We do this by again pointing to our “navigation” container; its first unordered list, and then our list items.
#navigation {width:150px; font-size:12px;}
#navigation ul {margin:0px; padding:0px; background-color:#666;}
#navigation ul li {
height:25px;
line-height:25px;
list-style:none;
padding-left:10px;
color:#FFF;
border-top:#fff solid;
border-bottom:#fff solid;
border-width:1px;
cursor:pointer;
}
Ok here we have a lot of styling to give to these list items that will cascade down our entire menus look and feel for the rest of the menus list items. So to begin we remove our default unordered list item styles, or rather bullets next to each list item. Next we set a height of 25 pixels to space our list items out vertically a little, but at the same time make up for text placement by using the line-height and left padding.
For the line-height, we set it exactly the desired height of the list item in order to center our text vertical within the list item. Our padding-left style is to move each list items text off the left site by 15 pixels. Our last CSS styles are purely for preference and deal with border colors and thickness, font color and cursor types. These last styles may also change according to your design.
Let’s take a look shall we.
Ok not too bad.
Before we move onto creating our second level sub menu, lets add some behavior to our menu shall we. Let’s give a color difference to our list items background color if we are hovering over them.
To do this we again reference to our “navigation” container first, then our first unordered list and then our list items them self. Once we are pointing to our menus list items we add a pseudo hover to begin the statement for our behavior.
#navigation {width:150px; font-size:12px;}
#navigation ul {margin:0px; padding:0px; background-color:#666;}
#navigation ul li {
height:25px;
line-height:25px;
list-style:none;
padding-left:10px;
color:#FFF;
border-top:#fff solid;
border-bottom:#fff solid;
border-width:1px;
cursor:pointer;
}
#navigation ul li:hover {background-color:#F90; position:relative;}
Here we are giving our list items a background-color of #F90 and set its position to be that of “relative”. We use relative because it turns our list items into stopping points for any immediate children that have a position of absolute vs. having the absolute element break out of our menu all together. We also get the position of relative to our list items here at the hover state in order to fix IE related issues.
Ok so here is what our menu behavior looks like.
Ok now we must move into our second level unordered list. We always nest our sub menus deeper within the list item we want it to be displayed under.
So make your HTML look like the following:
<div id="navigation">
<ul>
<li>Home
<ul>
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
<li>About</li>
<li>Contact</li>
<li>FAQ
<ul>
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
<li>News
<ul>
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
</ul>
</div>
Ok notice how we have added entirely new unordered lists to our first level list items we want a sub menu to appear. Great let’s move back up to our CSS and begin to set some visual rules to these second level unordered lists.
To give ruling to these second level unordered lists we again must traverse past our “navigation” container to our first level unordered list and then to our second unordered list like so.
#navigation ul ul {
display:none;
position:absolute;
left:75px;
top:5px;
border:#fff solid;
border-width:1px;
background-color:#999;
}
Here we are giving our second unordered list a display of none. We do this so that by default, our second level unordered lists are hidden until told so. Next we set our second unordered list to be a position of absolute so we may position it according to the location of its parent relative element. To position our absolute second level unordered lists we use the top and left styles. Our last styles are of preference and are for borders, border widths and background colors and may change in your design.
Ok so we have wrote our second level unordered list’s off behavior state so we now have to write our display behavior state. To do this we point to the first level unordered list and instate a pseudo hover. Next we point to our second level unordered list and give a display of block to display it out upon its parent being hovered, like so.
#navigation ul ul {
display:none;
position:absolute;
left:75px;
top:5px;
border:#fff solid;
border-width:1px;
background-color:#999;
}
#navigation ul li:hover ul {display:block;}
Great just a few more rules and styles are we are complete.
Ok the last two CSS rules for our second level unorderd list are primarly for structure purposes only. The first rule points to all our second level unorderd list items and restates the overall width of 150 pixels to reshure that our sub menu and its items will carry the same width as our overall menu. Next we set a float of left and a display of inline to fix any IE related issues. Finaly for personal likes I removed our previously stated border from the second unorderd list items.
#navigation ul ul {
display:none;
position:absolute;
left:75px;
top:5px;
border:#fff solid;
border-width:1px;
background-color:#999;
}
#navigation ul li:hover ul {display:block;}
#navigation ul ul li {border:none; width:150px; float:left; display:inline;}
The next, and last rule for the second level unorderd list is for visual purposes only and adds a pseudo hover behaviour to all our second level unorderd list items. Here we are giving our list items a text decoration of underline and removing any border from list items.
#navigation ul ul {
display:none;
position:absolute;
left:75px;
top:5px;
border:#fff solid;
border-width:1px;
background-color:#999;
}
#navigation ul li:hover ul {display:block;}
#navigation ul ul li {border:none; width:150px; float:left; display:inline;}
#navigation ul ul li:hover {text-decoration:underline; border:none;}
Let’s look at what we have so far.
Now let’s create our last level unordered list. Like before we are going to insert a new unordered list and items with in the level and list item we want to trigger or rather pop out this third level unordered list.
Here is what our final HTML would look like.
<div id="navigation">
<ul>
<li>Home
<ul>
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 2
<ul>
<li>Sub Sub Menu Item 1</li>
<li>Sub Sub Menu Item 2</li>
<li>Sub Sub Menu Item 3</li>
<li>Sub Sub Menu Item 4</li>
</ul>
</li>
<li>Sub Menu Item 3</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
<li>About</li>
<li>Contact</li>
<li>FAQ
<ul>
<li>Sub Menu Item 1</li>
<li>Sub Menu Item 3
<ul>
<li>Sub Sub Menu Item 1</li>
<li>Sub Sub Menu Item 2</li>
<li>Sub Sub Menu Item 3</li>
<li>Sub Sub Menu Item 4</li>
</ul>
</li>
</ul>
</li>
<li>News
<ul>
<li>Sub Menu Item 1
<ul>
<li>Sub Sub Menu Item 1</li>
<li>Sub Sub Menu Item 2</li>
<li>Sub Sub Menu Item 3</li>
<li>Sub Sub Menu Item 4</li>
</ul>
</li>
<li>Sub Menu Item 2</li>
<li>Sub Menu Item 3</li>
</ul>
</li>
</ul>
</div>
Great, because we have already stated most visual styles we want our menu to carry, these last few rules and styles are for structure only. To start we add a reset rule if you will, that will basically prevent our third level unordered list from being displayed until its proper parent and unordered list level has been hovered over. In other words, we don’t want our third level unordered list to be displayed when our first level unordered list is being hovered over but rather display it’s self only when our second level unordered list is hoverd.
Here is what this reset would look like.
#navigation li:hover ul li ul {display:none;}
Great let’s move onto the last few rules. Our first one is to offset our third level unordered list to the left further than its parent unordered list level. So again point to our third level unordered list and give it a left style of 110 pixels. I also added a different color background color here for kicks and to demonstrate you can define styles even further if you wish.
#navigation li:hover ul li ul {display:none;}
#navigation ul ul li ul {left:110px; background-color:#0099CC;}
Ok now we already created a reset rule that would keep our third level unordered list from being displayed, let’s crate our last rule that will finally display our third level unordered list out.
#navigation li:hover ul li ul {display:none;}
#navigation ul ul li ul {left:110px; background-color:#0099CC;}
#navigation ul ul li:hover ul {display:block;}
Great so here we point all the way down to our second level unordered list and assign a pseudo hover behavior to it. We then move onto pointing at the third level unordered list and set a display of block.
Let have a look see at what our vertical menu now looks like shall we?
Thats it everyone, you have just created a pure CSS vertical menu with sub level pop outs that is compleately cross browser friendly.
Here is a working example of the pure CSS vertical menu
PLEASE NOTE: The above example works in IE5 and IE6 because of the pseudo-hover fix that can be found here. Please read this pseudo-hover fix tutorial if you are trying to get this or even the Pure CSS Horizontal Menu to work in older versions of IE.
Thanks everyone.
Devin R. Olsen







Wow! Thanks. Great stuff. I’m using this CSS Vertical menu in my current project and look forward to coming back for other tutuorials.
Would you share what development environment you use? Looking at the code screen shots on other tutorials, the code looks well colored, easy to follow.
I will used :)
@Lt. D. Young,
Sounds to me like you need to give the anchor a “display:block;” style. By telling the anchor tag to behave like a block you can use “with:100%;” like you would with block like elements.
Hope this helps.
First, Great tutorial. Was able to grasp the concept within the first 10 minutes of analyzing. Now, I have run into a problem that I may need assistance with. The li:hover works great, until I add an anchor tag. I’ve gotten it to effect the font color change on hover, but only if you hover over the verbage itself. I’m trying a span for the width of the div & li – however to no avail. I know it has to be something very simple, as I have done it with a horizontal nav bar. I tried to merge the two sets of css, but i have run out of ideas. (not great for someone who’s been designing for 15+ years, eh?)
Please Advise.
Cordially,
Lt. D. Young
Great article, very easy to follow.
…please where can I buy a unicorn?
You have used “display”none” property and seo expert say hiding text using css is not advisible.
Very nice thanks a lot!!! I’m big fan your site
Nice tutorial, I learned some new tricks.
I used div’s instead of ul’s (I don’t really like ul’s) still your design man, thanks.
Absolutely as long as there is a link back I dont mind at all.
Hello from Russia!
Can I quote a post in your blog with the link to you?
In IE6 This Menu not Working
Easy to understand and learn.
thank you.
Dear author,
You just made my day. Thank you so much for this tutorial.
This tutorial helps a lot and probably the simplest to follow YET the BEST on the internet.
Thank you.
awesome man, exactly what I needed
http://www.devinrolsen.com – da best. Keep it going!
Bodyc
ok hi again,
I just found something out; in safari the sub is horizontal (preferable) and I checked another page in firefox and there it is vertical! How can i change it to horizontal?? (in the css)
Cheers Vincent
Hi, tnx for the great tutorial! I implemented it and it works great with safari, although I expected it to roll down instead of a horizontal menu, I am happy with it though.
But , when I checked it in Mac Firefox I see only the first submenu item. Any idea how to solve this
Many thanks
Vincent
Hi Susan, the code is correct. The problem was one of the example images was out of place. Please have another stab at the step by step tutorial again. I just went from start to finish and the end result was how it should be now.
Also note, each level of the menu is broken into chunks of code, we go over each chunk of code one rule at a time. Each new rule to each chunk of code is bolded to give relevance over this rule(s) we are talking about.
The wrong css code appears after this paragraph:
“To do this we again reference to our “navigation” container first, then our first unordered list and then our list items them self. Once we are pointing to our menus list items we add a pseudo hover to begin the statement for our behavior.”
It’s the same as the one before.
Would love to finish this tutorial.
Easy to use & good in look
Dude this is great!
I wish the link for the working example was valid :(
I always enjoy feedback from my readers.
great tutorial ,thank you so much
Nice tutorial, really learned something out of it. thx great!
nice
nice tutorial.. simple but helpfull.. thx..
Hello Devin. Think your website is excellent, one of the best tutroial website around the world. Great tutorials and excellent manner at explaining things. Keep up the good work All the best from Josh
Well thank you very much Josh. I have worked really hard at trying to provide only the basic fact here to my readers and will continue to do so. I know my updates to this site have slowed just a little due to work and another huge project I plan to release soon. With that said though I will be releasing a whole array of new tutorials here shortly, so stay tuned everyone.
can you give the link whrere I can download the cssHoverFix.htc for IE.
hey devin thanks fot this script but dude your css not work on ie6.
plz check it on ie6 and sent me revert back on my email id
singh.is.sandeep@gmail.com
sandeep In order to make either horizontal or vertical menus to work you must read my \”CSS IE Hover Fix\” tutorial for IE5 and IE6.
joney, you can download a copy of the cssHoverFix.htc at my \”CSS IE Hover Fix\” tutorial under tutorials pull out up top.
clean and simple, I appreciate the tutorial :-D
I remove the height on css so that when I have a long title menu it will move on the next line.My only problem when I hover on the blank space on first level the second menu didn’t show but when I hover it on the menu title it works. I got this problem on IE 5.5 and 6.
Cheers Devin! A tweak here and there, and its exactly what I was after. Thanks again.
nice job dear. its excellent.
Absolutely fantastic tutorial. Thank you very much.
good job……… thanx
Great menu Devin, Worked perfectly on ie6 for me
Devin. Outstanding work! I do have a problem on IE7. The third level reset only works once or twice when hovering over the first level. Then, when I hover over the first level again, the third level pops up, but with no links. Just the blue block. It then continues to do this until I refresh the page. Any hints? Thanks, frank.
Walaka, English please :)
nice job dear, thanx
Perfect example, just what I was looking for, thank you :-)
how to make more than 3 vertical drop down menus
cool menu without javascript;)
i learn a lot!!!
nice teaching……… thank u for spending ur time for this tutorial
Devin� Your code is really useful to me… I have one query… I have created the menu plus one submenu in the first cell of the table. In the next cell I have embedded one flas picture. If I move upon the menu now, the submenu gets hided behind the flash… Is there any solution to this….
i got it! thanks u very much!
If I want to add the second vertical menu on the right of the web page then how can I do that?
Very great and Detailed explanation, thanks alot
It’s not a menu until you actually add some links. I find it better if the whole cell is a link rather than just the text – how would you do this?
Very nice thanks a lot!!! just wish there was a css function \”click\”!!
walaka yeh tum kia karti hai