Need some help?

I'm usually available for small jobs or problem solving with jQuery or css, at reasonable rates. Just get in touch.

Web Hosting

We recommend Clook for web hosting. UK based, great service and great value.

CSS horizontal menu with dropdowns

I was looking for a simple tutorial for a css-only horizontal dropdown menu earlier this week, aimed at a css beginner. And I couldn’t find one, so here’s how to build this menu….

I’m going to do this in two stages:

Creating a simple horizontal menu – no dropdown

Before we get into the dropdowns, let’s just sort the horizontal menu bit. Let’s start with the html markup, which is a standard unordered list. Let’s have four menu items:

<ul id="horiznav">
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
</ul>

Nothing too exciting there. Now let’s have a look at the css:

ul#horiznav{
margin:0;
padding:0;/*set both to zero to remove browser inconsistencies*/
list-style-type:none;/*get rid of bullet points*/
height:32px/*just to avoid some possible float issues*/
}

#horiznav li{
float:left;/*float the li element so the menu's horizontal...*/
width:150px/*...and set the width*/
}

#horiznav li a{
display:block;/*make the link a block element...*/
width:150px;/*...with a fixed width...*/
line-height:30px;/*...and set the line-height to vertically centre the text*/
text-align:center;/*horizontally centre the text...*/
color:white;/*...colour it white...*/
text-decoration:none;/*...and remove the default underline*/
background-color:#EA9531;/*give the link an orange background...*/
border:1px solid white/*...and a white border...*/
}

#horiznav li a:hover{
color:#333333/*change the text colour on :hover*/
}

See comments in the css for an explanation. The key thing that’s making the menu horizontal is floating the <li> element. This code gives us this:

Adding the drop down

Now we’ll add the drop down. The dropdown elements are included as additional <ul> elements nested within the appropriate <li> element. Like this:

<ul id="horiznav">
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a>
     <ul>
     <li><a href="#">Item 2.1</a></li>
     <li><a href="#">Item 2.2</a></li>
     </ul>
</li>
<li><a href="#">Item 3</a>
     <ul>
     <li><a href="#">Item 3.1</a></li>
     <li><a href="#">Item 3.2</a></li> 
     <li><a href="#">Item 3.3</a></li>
     </ul>
</li>
<li><a href="#">Item 4</a>
     <ul>
     <li><a href="#">Item 4.1</a></li>
     <li><a href="#">Item 4.2</a></li>
     <li><a href="#">Item 4.3</a></li>
     </ul>
</li>
</ul>

Right, now for the css. We need to make a few additions – marked in red:

ul#horiznav, #horiznav ul{/*remove the bullets from the dropdown ul as well*/
margin:0;
padding:0;
list-style-type:none;
height:32px
}

#horiznav li{
float:left;
width:152px;
position:relative/*set position:relative as the start point for absolutely positioning the dropdown*/
}

#horiznav li a{
display:block;
width:150px;
line-height:30px;
text-align:center;
color:white;
text-decoration:none;
background-color:#EA9531;
border:1px solid white
}

#horiznav li a:hover{
color:#333333
}

#horiznav li ul{
display:none;/*hide the dropdown*/
position:absolute;/*position it absolutely..*/
left:0;/*...align the left edge with the left edge of the parent li...*/
top:32px/*...and 32px down from the top - 30px height + 2px for the border*/
}

#horiznav li:hover ul {
display:block/*display the ul when the parent li is hovered*/
}

#horiznav li ul a{
background-color:#FFB33B/*give the dropdown a different background colour*/
}

See the comments in the code for explanations. A surprisingly small amount of css, really. The dropdowns are normally hidden, and appear when the parent <li> is hovered. So this gives us (same as at the top of the page):

You’ll see that the use of absolute positioning makes the dropdown appear on top of anything else on the page – which is what we want. And this works fine in pretty much every browser in popular use today. Specifically I’ve tested in IE7, IE8, FF3, Chrome, Opera9, Opera 10, Safari4. You’ll spot there’s something missing. No prizes for guessing what browser causes a little extra difficulty…

Dealing with the dropdown in IE6

IE6 doesn’t support :hover, except on <a> elements. So without a bit of extra code, our nice dropdown won’t work at all in IE6. Fortunately, there’s a solution called csshover, which you’ll find here along with instructions on how to use it. I’ve personally found version 2 of this software to be the most reliable.

Adding animation with jQuery

To add some animation – fades, slides etc – have a look at my jQuery plugin here, which allows more sophisticated animation for javascript users while preserving the css approach for those without.

17 responses to “CSS horizontal menu with dropdowns”

  1. This is an excellent tutorial for menu bar. I have successfully generated a menu bar in my website with the help of this tutorial. Thank you for making a detailed and step by step tutorial.

  2. Shahbaz Ahmed says:

    VERY EXCELLENT AND SUPER Tutorial found,

    The BEST AND SUPER Easy Code

    Keep up
    Thanks

  3. Simon says:

    It’s utterly impossible to offer any suggestions here without seeing the live page, I’m afraid.

  4. Shashank says:

    I need help regarding drop down menu’s.
    1. I have 2 pages(eg. Page1 and Page2).
    2. Both pages have individual drop down menus.
    3. If I access each page individually, the drop down menu on each page work perfectly.
    4. Problem: But when I go from Page1 to Page2 then the drop down menu on page2 does not work.(vice versa.)

    Please help me out with some concrete solution..
    Thanks.

  5. Simon says:

    Have a look at this example, which has four levels of CSS menu under menu item 4.3. View the source to see the css.

  6. Chris says:

    Thanks!

    How would you go about doing another level of menu’s? I.E. 2.1.1, 2.1.2, 2.1.3, 2.2.1, 2.2.2, 2.2.3, etc. without using jQuery?

  7. Simon says:

    Sam
    You should be able to do this by amending the css as follows:

    ul#horiznav{
    margin:0;
    padding:0;/*set both to zero to remove browser inconsistencies*/
    list-style-type:none;/*get rid of bullet points*/
    height:32px/*just to avoid some possible float issues*/
    text-align:center
    }
    
    #horiznav li{
    display:inline-block;/*replace float with this...*/
    width:150px/*...and set the width*/
    }
  8. Sam Krishnan says:

    I am trying to center the horizontal menu but it keeps sticking to the left of the webpage.
    my content has a width of 70% and centers itself well. How do i do the same for the menu.

  9. Simon says:

    Well, my example page and your linked page work fine in IE9, but if it’s a different page with which you’re having the issue, then I’m guessing your doctype is missing or incorrect and the page is rendering in Quirks mode. You can check this by viewing the developer tools via F12 and checking the Document Mode.

  10. jorge says:

    Works great. Thanks for the code.

    Only problem for me is wont work with ie9. Any clues ???

    Thanks

  11. Sheetal says:

    Exactly.. What I am looking for…Being novice in web design..great tutorial..
    Thank you Simon!!

  12. Dan says:

    Perfect! Works great. Thank you!

  13. Simon says:

    Dan

    That sounds like simply a z-index issue. You’ll need to set the z-index on the container with the menu so that it’s higher than the z-index on the container with the slideshow. Remember you’ll need to set the position on each of these elements as well to make the z-index effective.

  14. Dan says:

    Great code! I set it up on 2 horizontal menus and on one vertical. Works great with one issue on the vertical menu. The submenu when you hover over it displays behind a css and java slideshow I have. Do you know what I need to change so it displays in front?

    Thank you

  15. Simon says:

    Have a try with making the following amendments:

    ul.horiznav {
        margin-bottom: 15px;
        text-align: center;
    }
    
    .horiznav li {
        display: inline-block;
        /*float: left;*/
        margin-right: -4px;
        position: relative;
        width: 152px;
    }

    You might need to play about with the negative right margin on the li element – this is needed to counteract the gap introduced between inline elements.

  16. msrosyidi says:

    Great and clear. But I’m still looking for the ways to center this menu with a fluid width.

  17. Anthony says:

    Nice. I’m going to use this template to on my “website” (just a test site for fun)… I’ll try the jquery animation too.

Useful? Interesting? Leave me a comment

I've yet to find a way of allowing code snippets to be pasted into Wordpress comments - so if you're trying to do this you'd be better off using the contact form.