
Last week, CSS Newbie reader Andrea Pluhar wrote in with an interesting problem: she wanted to use CSS dropdown menus like the ones we featured last week on a website that she was building, but the design called for the submenu to be arranged horizontally, not vertically. She sent me a mockup of what she was after (excerpted above) and wondered if there was a way to accomplish this effect using CSS. It turns out that there is a CSS-riffic way to do this, and in the spirit of maximizing benefit, I thought a tutorial would be in order.
The XHTML involved is identical to that used in our regular dropdown menus: a nested unordered list, where the nested lists become the submenus. It looks something like this:
1 2 3 4 5 6 7 8 | <ul id="navbar"> <li><a href="#">Item One</a><ul> <li><a href="#">Subitem One</a></li> <li><a href="#">Second Subitem</a></li> <li><a href="#">Numero Tres</a></li></ul> </li> <!-- ... and so on ... --> </ul> |
Next we’ll move to the CSS. I started out by moving the navigation bar to the top-right corner, like the design called for, removing the list styling, and floating the items left to make them line up in a row:
1 2 3 4 5 6 7 8 9 | #navbar { position: absolute; top: 0; right: 0; margin: 0; padding: 0;} #navbar li { list-style: none; float: left; } |
Next, I styled the primary anchor tags to make them look more like the navigation Andrea was looking for. The code looks like this:
1 2 3 4 5 6 7 8 9 | #navbar li a { display: block; padding: 3px 8px; text-transform: uppercase; text-decoration: none; color: #999; font-weight: bold; } #navbar li a:hover { color: #000; } |
I’ve added a bit of padding to the link, and used the text-transform property to make everything uppercase like the mockup called for. That way, the original XHTML can be lowercase or camel-case (capitalized first letters)… which would be a little easier to read in an unstyled document.
Next up, we hide the nested lists by default, and then style them when the containing list item is hovered over:
1 2 3 4 5 6 7 8 9 | #navbar li ul { display: none; } #navbar li:hover ul, #navbar li.hover ul { position: absolute; display: inline; left: 0; width: 100%; margin: 0; padding: 0; } |
The code above is the bit that really makes most of this magic work, so I’ll explain the important parts in some detail. First, because IE6 doesn’t support hover states on anything other than anchor tags, we’re writing our rules to account for the hover state and a hover class. This class is applied to elements when they’re being hovered over, using an ingenious little bit of JavaScript (which is explained in this previous dropdown menu tutorial).
Next up, we’re absolutely positioning our nested lists and using the “left” property to move the list to the left-most side. This isn’t moving the list to the left-most side of the screen, but instead the left-most side of its parent positioned element, which in this case happens to be the main unordered list that we positioned right at the start. As such, this trick relies of the whole list being positioned in some manner, even if it’s just relatively positioned and left in place.
The display: inline rule is a little more complicated. So much so, I don’t even completely understand what it’s doing. What I do know is, without that rule, the list items in the submenus simply don’t show up whatsoever in any major browser. I think it has something to do with the fact that the containing elements are floated (which we’ll get to in a bit), but I can’t prove that. If anyone has any better insight into the technical aspect, please let me know in the comments.
Lastly, the width: 100% rule is somewhat important. It’s preventing the unordered list from collapsing down to a smaller size in certain browsers. Specifically, without setting this width specified, the nested list sometimes collapses to the size of its “containing” list item (even though it’s absolutely positioned and therefore technically no longer contained). Note that older versions of Opera don’t deal well with the 100% width… if you want it to work on older versions, you’ll need to specify a width according to a definite size (such as pixels). However, the most recent version of Opera (9.27) handles it fine, and I get the impression that Opera users tend to upgrade more frequently than, say, IE users.
Finally, we just float the elements left (to put them in a nice horizontal row), and give them some colors:
1 2 3 4 5 6 | #navbar li:hover li, #navbar li.hover li { float: left; } #navbar li:hover li a, #navbar li.hover li a { color: #000; } #navbar li li a:hover { color: #357; } |
And that’s it! You can see a working example here. This has been tested and works fine in IE 6+, Firefox 2, Safari (Mac and PC), and Opera 9.27.
The only portion of the mockup I wasn’t quite able to duplicate was a way to keep the primary menu item highlighted when the submenu was in use: because the nested list is absolutely positioned, the browser doesn’t seem to consider them a matched set any longer (except, it seems, in terms of default width). If anyone has a solution to this bit, I would love to hear about it!
Thanks to Andrea for inspiring a hopefully useful tutorial! And if you ever have a CSS-related question that you think might make a good article here, don’t hesitate to send me a message, either via my contact page or on Twitter. I can’t guarantee I’ll use every question posed, but I’ll do what I can as time and situation allow.


On May 22, 2008
11:09AM
Michael said:
Tks for the tut.
I do believe though that all specified floats (e.g. #navbar li) also need to have a width specified — even if it’s set as ‘width: auto;’
display:inline is needed so each li aligns horizontally (“in line” with each other). This is generally used for IE ONLY.
On May 25, 2008
2:58AM
agentsarah6 said:
Where are the source files?
On June 18, 2008
3:00AM
Gina said:
Like the tutorial. Would it also be possible to do this without using any java script?
On June 18, 2008
7:36AM
Rob said:
Agentsarah6: You can see all the source information if you click through to the example.
Gina: You can do it without JavaScript, presuming you don’t care if it works in IE6 or not. But if you need IE6 support, you need the JavaScript, because IE can’t handle hover states on list items, which is how the dropdown thing works. :)
On September 13, 2008
3:42PM
Sophie said:
Hello, I have the task of converting our company website to CSS. I found your horizontal drop down which I think will work great. As a novice I feel a bit bogged down with the CSS but am definitely improving. I hope this isn’t a stupid question but what would I have to change in the html and css files to add further sub menus.
On September 14, 2008
8:11AM
Danh ba web 2.0 said:
Great tutorial !
Thanks you very much
On October 17, 2008
10:58PM
Vowels said:
Using this. Thank you very much!
On October 18, 2008
12:38AM
eddy said:
ive been trying to find a tutorial like this THANKS!
On December 08, 2008
12:19PM
elvisparsley said:
Question.
When I see your code, http://www.cssnewbie.com/horizontal-dropdown-menus/ I found js code,
// Javascript originally by Patrick Griffiths and Dan Webb.
// http://htmldog.com/articles/suckerfish/dropdowns/
…
…
What is this js for?
The menu works without js, then why did you put this code?
Thanks for your tut.
I didn’t know your website until today.
On January 13, 2009
11:29AM
Cameron said:
I noticed that when the width of the browser hugs the side of the website in IE6…and you rollover the menu items a horizontal scroll bar appears. Only got this result in IE6 on WinXP Pro.
On March 15, 2009
9:13PM
Jim said:
I have just been learning about this, thank you. I however, could not get the sub-menus to be horizontal, just vertical. I tracked it down to having the 1st line in the file e.g., <!DOCTYPE… without this line your horizontal.html example has the sub menus vertical as well. I don’t understand the full implications of this line. Anyone know of a reference?
Thanks,
Jim
On March 16, 2009
8:43AM
Rob Glazebrook said:
Elvis: That code is so IE6 plays nicely like all the other browsers. Without it ~most~ browsers will be perfectly fine. Just IE. The reason is, IE doesn’t support hover states on anything but anchor tags.
Jim: That line is pretty critical to modern web design techniques. Among many other things, it’s the line that tells Internet Explorer how to behave: with that line, IE goes into “Standards” mode and behaves like it should. Without it, IE goes into “Quirks” mode, where it behaves like a Website of Yesteryear, back when people used tables and font tags to make everything.
On March 17, 2009
3:57AM
andri said:
thanks so much..
ive try this but always stack in IE..
thanks
On May 07, 2009
9:08PM
Laura said:
Thank you so much. This worked first time around – when does that ever happen? Really appreciate you putting this out there.
On June 05, 2009
11:36PM
Sebastian said:
I need help! I have used your tutorial and modified it a bit, though i cant find a way to color the whole Box when the mouse goes on a submenu link?!? how do i do that? this is the code I have:
#navbar {
position: absolute;
top: +7px;
margin: 0;
padding: 0;
width: 100%;
font-size:10px;
}
#navbar li {
list-style: none;
float: left;
position:relative }
#navbar li a {
text-decoration: none;
color: #fff; }
#navbar li a:hover {
color: #fff;
text-decoration:underline;}
#navbar li ul {
display: none; }
#navbar li:hover ul, #navbar li.hover ul {
line-height: 15pt;
background:#353637;
position: absolute;
display: block;
left: -8px;
top: 12px;
width: 200px;
margin: 0;
padding: 8; }
Home |
Servizi |
Pulizia di cantieri
Pulizia di manutenzione
Pulizia di facciate
Pulizia di vetri
Pulizia di edifici
Pulizie speciali
Altre prestazioni |
Referenze |
Contatti
On August 24, 2009
3:48PM
captain pixels said:
I “borrowed” this implementation of a horizontal menu using unordered lists (http://www.cssnewbie.com/example/css-dropdown-menu/horizontal.html) on a website and I was wondering if there is a way to introduce a delay (using Javascript perhaps?) on the drop downs so the submenus don’t close until after a determined amount of time. Say 2 or 3 seconds after the mouse over. Someone commented to me that sometimes they can’t get to the submenu items when they accidentally rollout and they have to go back and re-reveal the menus, which can get somewhat frustrating. Anybody has any thoughts on how to accomplish this? Great tutorial by the way!
On October 14, 2009
10:05PM
Mandi said:
In regards to captain pixels comment – I can’t get my secondary menu to stay long enough to click on at all… have i done the javascript wrong?
Please Help!
http://www.fws.org.au/141009.php
http://www.fws.org.au/css/fws1.css
#navbar {
position: relative;
top: 7px;
right: 15px;
margin: 0;
padding: 0 0 25px 0;
width: 908px;
font-size: 0.7em;
left: 25px;
}
#navbar li {
list-style: none;
float: left;
}
#navbar li a {
display: block;
padding: 3px 8px;
text-transform: uppercase;
text-decoration: none;
color: #FFF;
}
#navbar li a:hover {
color: #FFF;
background-color: #666;
background-image: url(../images/arrow.gif);
overflow: visible;
background-repeat: no-repeat;
background-position:center;
}
#navbar li ul {
display: none;
padding: 7px 0 0 0;
}
#navbar li:hover ul, #navbar li.hover ul {
position: absolute;
display: inline;
left: 0;
width: 100%;
margin: 0;
padding: 7px 0 0 0;
}
#navbar li:hover li, #navbar li.hover li {
float: left;
text-decoration: none;
padding: 7px 0 0 0;
}
#navbar li:hover li a, #navbar li.hover li a {
color: #FFF;
}
#navbar li li a:hover {
color: #FFF;
background-color: #666;
}
On October 26, 2009
11:07AM
Jim said:
Great tutorial.
How does one create a “current state”. So that when “events” is clicked, the secondary menu does not disappear when the mouse is moved from the menu. I still want to maintain the hiding of the secondary menu when the user first arrives
On November 04, 2009
7:42AM
winburner said:
you guys saved my life :)
thx alot for this article!
On November 04, 2009
1:12PM
Umeko said:
You are my goddamned hero. I’ve been trying to get this kind of menu working for a week now, and thanks to you it’s finally working!
On January 31, 2010
10:28AM
Stacy said:
Thanks so much! This is exactly what I was searching for.
On February 02, 2010
10:36AM
Shen said:
Thank you for tutorial!!! It works perfectly!!
On February 03, 2010
9:17AM
Benjamin said:
Hey … i’m from Germany – so sorry for my English – well done job !
But i have one question. Is it possible, that the dropdown-menu works onClick and not onMouseOver ? And that the dropdown-menu stays after klick to a link ? so i mean – if i click on a submenu, the new .html site appears, but the navi leaves. so – are there any possibilities to change?
Benny
On April 30, 2010
12:57PM
Raquel said:
hi i’ve been searching for days for a multilevel horizontal navbar, is it possible to make one with 4 levels following the structure you have here???
On June 16, 2010
5:28PM
Bryan said:
I’m trying to get the nav and subnav centered. Is that possible? The floats are mucking things up. Can this be done using display:inline?
On June 25, 2010
4:00PM
James said:
Great work. Works great in FireFox, but in IE the lower levels are stacked instead of across. Help. Ideas?
Thanks
On July 19, 2010
12:34PM
Heather said:
I have figured out how to get the hover state of the primary nav item to stay active once the user hovers over the subnav items. It turns out that simply adding the :hover declaration to the primary will make the hover stay active.
example:
ul#primarynav>li a:hover, ul#primarynav>li:hover {
background:#81010E url(images/nav-bg-hover.gif) repeat-x;
background-position:0px -10px;
height:37px;
}
I used the > between the ID and the element to make sure the hover applied only to the first li, and not the subnav’s li also.
On July 20, 2010
5:17AM
Ataollah said:
I was wondering how can we make it vertical not horizontal
On July 20, 2010
5:22AM
Ataollah said:
actually i tried it and it was vertical thnx 4 the awesome tutorial
On July 20, 2010
5:23AM
Ataollah said:
thnx there i no need i tried it and got the result i needed
thnx 4 the awesome tutorial
On July 20, 2010
6:03AM
Ataollah said:
Hey guys i was wondering if u knew how to make a vertical drop down menu like the ones on rado.com, thought this tutorial is awesome and helped me a lot i was wondering if it is possible to make it slide out instead of appearing suddently
On July 21, 2010
4:00PM
Dave Bowers said:
Hi Rob,
I was wondering how I could add a 2nd row of sub-navigation to this. Any help would be great.
On August 23, 2010
4:51PM
Barnamah said:
Where is the demo sample?
On September 06, 2010
6:27AM
cihip said:
Horizontal CSS Dropdown Menus post for thanx.
On September 07, 2010
10:47AM
Anuj said:
Still struggling to make it work on IE7. It does work fine on IE8 and firefox.
I have the javascript code that you mentioned a fix for IE6 but doesn’t help with IE7.
Any other suggestion to make it working on IE7.
Thanks.
Below is the css and javascript that I am trying:
CSSnewbie Example: Horizontal CSS Dropdown Menus
/* These styles just pretty up the page a bit. */
body {
font: 62.5%/1.2 Arial, Helvetica, sans-serif;
background-color: #eee; }
.wrap {
position: relative;
font-size: 1.2em;
width: 100%;
padding: 10px 1px;
margin: 0 auto;
margin-left: 0px;
background-color: #0080C8;
position: relative;
}
/* These styles create the dropdown menus. */
#navbar {
position: absolute;
top: 0;
left: 0;
margin: 0;
padding: 0;}
#navbar li {
list-style: none;
float: left;
}
#navbar li a {
display: block;
padding: 3px 12px;
text-decoration: none;
color: white;
font-weight: normal;
}
#navbar li a:hover {
color: rgb(0, 67, 110);
}
#navbar li ul {
display: none;
}
#navbar li:hover ul, #navbar li.hover ul {
position: relative;
display: table;
left: 0;
width: 100%;
margin: 0;
padding: 0;
}
#navbar li:hover li, #navbar li.hover li {
float: right;
background-color: #0080C8;
border-bottom: 1px solid #ccc;
border-top: 1px solid #ccc;
border-right: 1px solid #ccc;
border-left: 1px solid #ccc;
}
#navbar li:hover li a, #navbar li.hover li a {
color: rgb(0, 67, 110);
}
#navbar li li a:hover {
color: white;
}
// Javascript originally by Patrick Griffiths and Dan Webb.
// http://htmldog.com/articles/suckerfish/dropdowns/
sfHover = function() {
var sfEls = document.getElementById(“navbar”).getElementsByTagName(“li”);
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover=function() {
this.className+=" hover";
}
sfEls[i].onmouseout=function() {
this.className=this.className.replace(new RegExp(" hover\\b"), "");
}
}
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
On September 08, 2010
11:21AM
jordyjes said:
excelente aporte amigo
On September 13, 2010
2:18AM
Affordable web solutions said:
Nice css menu. Clean code. Is there any way integrate this menu so submenu will go up instead of down or side. Great to see a response or link if anyone know..
On September 19, 2010
8:42PM
Rae said:
Hi There
Love the code, but having trouble making it work on IE8. I get the menu structure, but no drop downs.
Here’s my CSS:
#navbar {
margin: 0;
padding: 0;
height: 1em; }
#navbar li {
list-style: none;
float: left; }
#navbar li a {
display: block;
padding: 3px 8px;
color: #fff;
text-decoration: none; }
#navbar li a:hover {
color: #FFFFFF;
background-color: #BB2635;
}
#navbar li ul {
display: none;
width: 10em; /* Width to help Opera out */
}
#navbar li:hover ul, #navbar li.hover ul {
display: block;
position: absolute;
margin: 0;
padding: 0; }
#navbar li:hover li, #navbar li.hover li {
float: none; }
#navbar li:hover li a, #navbar li.hover li a {
background-color: #263F84;
border-bottom: 1px solid #FFFFFF;
color: #FFFFFF; }
#navbar li li a:hover {
background-color: #BB2635; }
#navbar li:hover ul, #navbar li.sfhover ul {
display: block;
position: absolute;
margin: 0;
padding: 0; }
And the HTML Code:
Home
Services
Consulting
Workshops
Facilitation
Keynotes
About Anne
Photographs
Cartoons and Caricatures
Anne in the Media
Anne at Play
Resource Centre
Bookstore
Client Access
Contact Us
On September 29, 2010
12:18AM
Rey Sarmiento said:
Nice and simple example, with a little more styling it can become a nice handy snipet.
On October 09, 2010
11:54AM
macinfo said:
Really great and at the same time simple code!
One thing I’d really like to see added would be, that the sub menu items are horizontally centered under the hovered top navbar item. Would this be feasible?
On November 08, 2010
5:34AM
kirsty said:
This doesn’t work in ie6!?!
On November 16, 2010
8:22PM
aquafortis said:
This was exactly what I was looking for, and easy to implement–thanks so much! I have one question, and it might be a stupid one: I just noticed that the menu hugs the right side of the window when I increase the size of the window. That is, rather than staying in a fixed position within the confines of my header layout, its position stays relative to the right side of the browser window. You can see it in action at http://www.sarahjamilastevenson.com
It’s happening in Firefox & Safari. I haven’t checked IE yet. Not a huge problem, but it looks weird when the window’s too wide. I would so much appreciate any suggestions. Thank you!
On November 17, 2010
8:33AM
Rob Glazebrook said:
Hi Aquafortis,
Absolute positioning does that, but there’s a trick to get it to do what you want. Just add “position: relative;” to its parent element (in this case, your “header” div). Absolutely positioning something inside of a relative positioned element means it’ll position according to the confines of the relatively positioned element, instead of the whole page. You can read more on that here.
Your code would look something like this:
.header {
position: relative;
}
And to keep things nice and tidy, I’d just add that one line to your existing .header rules in your CSS.
On November 17, 2010
2:08PM
aquafortis said:
Thank you SO MUCH! The site is gorgeous and perfect now. :) I’ll definitely be reading your article on positioning. It’s one aspect of CSS that kind of hurts my brain, although what you said makes perfect sense.
On January 04, 2011
9:35PM
El Smurfa Diablo said:
Great article! Have there been any responses on going another level or two on into the sub-menus?
Thanks!
On January 08, 2011
4:24PM
Kim said:
To add a second level of navigation insert another ul within the subitems between the li tags.
Also add an id to the second ul. Then just apply the same css styles to the submenu id. You may need to add !important after some of these styles or they will just inherit the ones from navbar.
Item One
Subitem One
Subitem One
Second Subitem
Numero Tres
Second Subitem
Numero Tres
Hope this helps.
On January 23, 2011
12:28PM
SEO said:
nice tutorial, thanks a lot.
On January 23, 2011
12:29PM
Kitchen mixer taps said:
Great article! Have there been any responses on going another level or two on into the sub-menus?
Thanks!
On February 02, 2011
7:07AM
Antalya Ajans said:
Thnks for share but not preview?
On February 11, 2011
2:02PM
Alan Haynes said:
I was looking for an easy cross-browser menu solution and found it here. Thanks for the help.
On February 14, 2011
3:40PM
Kristina said:
Hi,
Great tutorial, even after finding it a couple of years after it was originally written, I found it to be quite helpful.
I have a question (for anybody reading this as well, not just for Rob). Is there a relatively simple way to add a sort of “saved state” function? To use Andrea’s mock-up as an example, if a user were to click on the “Current Exhibit” link in the navigation, is there a way to make it so that when the new page loads, the menu bar already has the “Exhibits and Events” submenu visible and the “Current Exhibit” link highlighted?
On March 15, 2011
1:56AM
Phil Best said:
I need to convert my ugly website horizontal bar menu so that it looks more like this one http://www.digitaltree.com.au/
Any idea how to do it?
On March 20, 2011
9:00PM
Loc said:
if I was on “Item One” page and would like to leave it highlighted, so people would know that I am on that particular page. How do I go about doing it?
tks
On March 23, 2011
7:14AM
Simon T8W said:
Hey is there a way to make the menu stay active while the dropdown is being hovered upon I mean like for instance the Exhibit and Events will stay black whiles the dropdown is active. I hope you understand what I mean. Please help me I’m sure this is a javascript thing but I can’t seem to do it :(
P.S i love your dropdown menu and want to use it please reply soon
On March 24, 2011
4:46AM
Kelvin Castelino said:
Hey do u know any ways in css that I can delay the dropping of the sub menu???
On March 31, 2011
6:09AM
sahibinden said:
Thank you very much for sharing very nice told:|
On April 14, 2011
4:08AM
welly said:
This is great, but I need a little mod to make it fantastic!
How would you go about making a “current” state, so that when a user clicks on a top level menu item, it’s sub navigation remains visible on that page? This would save users having to hover over the parent menu item to view it’s sub menu once again.
This would have to be flexible enough that when a user hovers over a different pages parent menu item the corresponding sub navigation appears.
On April 22, 2011
3:33PM
mrsd said:
Great tut! Was wondering if anyone could help me figure out how to center the sub menu instead of it being left aligned to the container. Any suggestions would be greatly appreciated!
On May 22, 2011
11:46PM
Enzo Schahin Carità said:
Muito obrigado pelo tutorial salvou a vida aqui e um job que tava dependendoo desse menu……coloca no google tratudor portuguese, ok!
Abs
On July 22, 2011
4:14AM
Nargile said:
Thank you so much:))
On July 22, 2011
4:18AM
Andezit Taşı said:
Thank you very much for sharing very nice
On October 05, 2011
3:51AM
w3digg said:
Hey Andrea Thanks for a Great Tutoril.
On October 05, 2011
3:52AM
w3digg said:
Hey Andrea Thanks for a Great Tutorial.
On November 11, 2011
6:59AM
debendra said:
how to create a drop down menu in table concept
On December 22, 2011
3:00PM
Luis Pumaricra Diaz said:
Hello, justo lo que estaba necesitando.
muchas gracias…
Slds..
On January 18, 2012
9:38AM
Alex said:
Intersting article. I’m looking for this for my blog. Thanks
On January 25, 2012
11:08AM
sandi said:
How does one keep the first tab open, so it features the sub menu.
By open I mean, I would like to have the navigation’s first tab (only), appear hovered over, showing the sub menus…is there a script to feature this?
Thanks,
Sandi