Horizontal CSS Dropdown Menus

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:

<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:

#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:

#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:

#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:

#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.

23 Comments

  1. 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.

  2. On May 25, 2008
    2:58AM

    agentsarah6 said:

    Where are the source files?

  3. On June 18, 2008
    3:00AM

    Gina said:

    Like the tutorial. Would it also be possible to do this without using any java script?

  4. 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. :)

  5. 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.

  6. Danh ba web 2.0 said:

    Great tutorial !
    Thanks you very much

  7. Vowels said:

    Using this. Thank you very much!

  8. eddy said:

    ive been trying to find a tutorial like this THANKS!

  9. 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.

  10. 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.

  11. 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

  12. 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.

  13. On March 17, 2009
    3:57AM

    andri said:

    thanks so much..
    ive try this but always stack in IE..
    thanks

  14. 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.

  15. 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

  16. 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!

  17. 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;
    }

  18. 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

  19. winburner said:

    you guys saved my life :)
    thx alot for this article!

  20. 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!

  21. Stacy said:

    Thanks so much! This is exactly what I was searching for.

  22. Shen said:

    Thank you for tutorial!!! It works perfectly!!

  23. 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

8 Responses Elsewhere

  1. On May 21, 2008
    12:52AM

    Menú horizontal desplegable muy sencillo con CSS » Cosas sencillas said:

    [...] el rastro a un enlace de CSS Globe, encuentro en CSSNEWBIE, donde tenemos un tutorial sobre la creación con CSS, de un menú horizontal principal, en donde [...]

  2. 5 Great Uses for the CSS Display Property - CSSnewbie said:

    [...] Without the CSS display property, fancy dropdown menus would be limited to the realm of JavaScript. However, by combining CSS’s display property and the :hover pseudo-class, you can create beautiful dropdown menus without a single line of JavaScript. Want to learn how? Here’s a tutorial on creating easy CSS dropdown menus, and here’s a second tutorial on creating special horizontal dropdowns. [...]

  3. css horizontal drop down menu – Open Source Design - fall09 said:

    [...] promised, here is the site for the drop down [...]

  4. Mike Capson » Blog Archive » The Best CSS Newbie Articles of 2009 said:

    [...] Horizontal CSS Dropdown Menus. This was the clear winner of the popularity contest. Last year, more than 7% of the site’s pageviews went to this one article! Horizontal dropdowns must be a popular design tool these days. [...]

  5. Saint John Web Design | Informative Computer Solutions » Blog Archive » The Best CSS Newbie Articles of 2009 said:

    [...] Horizontal CSS Dropdown Menus. This was the clear winner of the popularity contest. Last year, more than 7% of the site’s pageviews went to this one article! Horizontal dropdowns must be a popular design tool these days. [...]

  6. A Super Simple Horizontal Navigation Bar said:

    [...] while I’ve written tutorials on tabbed navigation bars, dropdown navigation bars, and even horizontal dropdown navigation bars, I’ve never stopped to explain how to build a basic, no-frills horizontal navigation bar. And [...]

Leave a Comment