Create dropdown menus with CSS only

I rarely see drop down menus that behave like drop down lists, but I really like them. I noticed, however, that people often use JavaScript to achieve this effect. Actually, there is a simple way to do it only with CSS.

View demo

You are probably familiar with the menu structure; nested unordered lists are common way to create menus.

Showing/hiding child menus is done with simple CSS: ul > li:hover ul. By using this selector we can define behavior of all child menus. When creating normal menus, besides display:block we set some other styles like background color and so on. The only difference between regular menus and “drop down list menus” is in the fact that we don’t set styles for nested UL but rather for LI that is hovered (ul > li:hover).

#header { height:120px; position:relative;
background: transparent url(header_bkg.png) repeat-x scroll top center;}
#nav { margin:0px; padding:0px; position:absolute; top: 70px; display:block;}
#nav > li { list-style-type:none; float:left; display:block; margin:0px 10px; 
position:relative; padding:10px; width:100px;}
#nav > li:hover ul { display:block; }
#nav > li:hover { background-color:#808080; -moz-border-radius:10px; -webkit-border-radius:10px; }
#nav li ul { margin:0px; padding:0px; display:none;}
#nav li ul li { list-style-type:none; margin:10px 0 0 0;}
#nav li ul li a { display:block; padding:5px 10px; color:#A2E200; text-decoration:none;}
#nav li ul li:hover a { background-color:#606060; -moz-border-radius:5px; -webkit-border-radius:5px;}
#nav li span { cursor:pointer; margin:0px 10px; font-weight:bold; }

This is how it can be done jus with CSS. I really can’t figure out why would someone use JavaScript for this, except for adding animations or other effect. Please note that this code doesn’t work in IE6 (this poor browser just doesn’t know what ul > li means).

30 Responses

  1. Allan 20. June 2009 at 23:36

    You said:
    "I really can’t figure out why would someone use JavaScript for this"
    But then you turn around and say:
    "Please note that this code doesn’t work in IE6"

    Have you not been doing this for very long? :-) Professional developers, up until very recently, HAD TO SUPPORT IE6 (some still do). That meant using Javascript for this sort of thing. We’ve all known it’s been possible using only CSS, but if it didn’t work in the browser with 80% market share …

  2. Janko 21. June 2009 at 11:12

    Allan: Yep, that was a good reason to involve JS. With all those anti-IE6 campaigns and browser stats today I’m beginning to feel as if IE6 was just an ugly dream. :)

  3. Janko 21. June 2009 at 13:01

    As the matter of fact, this menu can be functional in IE6 if you add links to top-level items (spans inn this example) that will point to different sections (and use "ul li" selector instead of "ul>li"). So, IE6 users won’t have full visual experience but they will have functional navigation. I think that fair price.

    Is it me talking to myself about E6? That’s not good :)

  4. Chad 21. June 2009 at 15:07

    I actually use this method on most of my sites. It’s a very quick, solution for IE6. You just have to paste this JS in there…

    sfHover = function() {
    var sfEls = document.getElementById("mainMenu").getElementsByTagName("LI");
    for (var i=0; i<sfEls.length; i++) {
    sfEls[i].onmouseover=function() {
    this.className+=" sfhover";
    }
    sfEls[i].onmouseout=function() {
    this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
    }
    }
    }
    if (window.attachEvent) window.attachEvent("onload", sfHover);

    Change "mainMenu" to the ID of your top UL and just add a class called "sfHover" for IE6.

    You can find this solution at http://htmldog.com/articles/suckerfish/dropdowns/

    Great post Janko!

  5. Kiplog 21. June 2009 at 17:09

    Two things from Eric Meyer’s book "more Eric Meyer on CSS":

    The #nav selector causes a bug in IE6 – really weird. Use div#nav and it works.

    His example uses a .htc file to make a hover state on the li (IE doesn’t let select the hover state on anything but an ‘a’). Same result as Chad’s comment.

  6. Janko 21. June 2009 at 17:25

    Chad, Kiplog: I didn’t know for #nav bug in IE6. Yep, adding JS will make it fully functional. However, you can avoid JS completely and make it functional by adding link to section to top level items. Limit visual experience for IE6 users but make the navigation functional ;)

  7. webmasterdubai 21. June 2009 at 20:39

    nice and good menu and simple.

  8. Davide Espertini 22. June 2009 at 10:19

    Nice Janko! Great tut, and really simple explanation! :D

  9. Mat 22. June 2009 at 16:26

    A lot of pseudo classes simply don’t work on elements other than <a> in IE6 as well, this is another drawback. It’s just not fun to be applying hacks for every little thing IE6 can’t handle, when javascript could fix it fairly easily.

    I personally would love a pure CSS solution, the problem is, IE6 is still very much in demand for a lot of people, take for instance, my client. She sends me PSDs (works in advertising) and has me create templates and do ajax work for her, and she insists on having everything visually the same across all modern browsers + IE6….it’s just too common still, it’s really silly how we have to support this stuff.

    Sometimes I feel like we’re stuck in the same rut with the same problems we had 5-10 years ago.

  10. Webdesign Meppel 22. June 2009 at 19:17

    Clear explanation and nice method. Though I prefer combining css with javascript which offers a lot more possibilities. Especially when it comes to positioning of the dropdowns, cross-browser compatibility and flexible widths of the menu items.

  11. Janko 22. June 2009 at 21:49

    Davide: ;)

    Mat: I agree. That’s why I think IE6 users should have a functional website, but with limited visual appearance. As for the menus. However, I know it might be tough to explain that to client. I always negotiate about this stuff with clients. Sometimes I even win :)

    Webdesign Meppel: Sure, JS (especially jQuery) can significantly improve overall experience.

  12. douglasfugazi 23. June 2009 at 08:31

    very nice!!
    thanks for sharing :)

  13. aravind 25. June 2009 at 18:21

    Awesome Janko! Its great that you have shared this trick.
    Many of the designers don’t even know that such a method exists.. :-)

    Even though you should have elaborated more..
    Beginners may get confused seeing the code :P

  14. mateu 25. June 2009 at 23:31

    IE 6 não funciona !

  15. jro 29. June 2009 at 03:06

    I’m fairly new to web design, and it’s awesome to know that this can be done with just CSS. I still tend to stay away from Javascript when I can, because despite learning the basics, I still find it all a little confusing.

    Though I do find the code used here a little complex still. Takes a lot of thinking to figure out exactly what is going on. /*Comments*/ defining everything would make it a little easier.

  16. Viteb 29. June 2009 at 06:43

    Nice stuff indeed! It is truly brilliant idea.

  17. duellsy 6. July 2009 at 13:25

    As noted by a few other people… this solution isn’t supported by a massive market share, so isn’t really a ‘solution’ ;)

  18. James 15. July 2009 at 13:28

    Good menu. Actually, most unsupported CSS and some other issues (transparent PNG support for one) can be corrected using the IE7/8.js from:

    http://ie7-js.googlecode.com/svn/test/index.html

    Obviously as allways, the code should fallback gracefully and still be functional incase the user has blocked\disabled or cant use javascript.

    Good menu Janko, thanks for sharing.

  19. Terry 3. August 2009 at 18:02

    You can use Whatever:hover found here (http://www.xs4all.nl/~peterned/csshover.html) to get IE6 to recognize the :hover when used with elements other than anchor tags. The menu remains virtually pure CSS and is cross browser compatible.

  20. Pritee 4. August 2009 at 07:17

    Nice trick to learn how can we create css menu but professionally not worth using it just becoz its not working in IE. But Nice to learn how can we make css menu and we can us it with javascript.

  21. SI Web Design 4. August 2009 at 08:19

    Please people, forget about IE6. Even Microsoft had officially set IE8 for all their updates!
    http://ie6update.com/

  22. Bradford Sherrill 4. August 2009 at 17:23

    Great post! @ SI Web Design, you can not forget IE6 what browser do user’s use while at work? (IE6) Until IT Departments jump from IE6 or even XP it will be a long time. People still buy things and make personal decisions while at work. Sad but true.

  23. Christhebliss 4. August 2009 at 19:23

    Allan, IE6 had around 15% of the market when you wrote your comment. Today, Firefox has almost 50% of the market, so… IE can’t have almost 80%. All according to W3C.

  24. M Hussain 7. August 2009 at 11:14

    Thanks for a nice article

  25. Azza 14. August 2009 at 20:47

    Agreed with Christhebliss. Here’s the stats:

    http://www.w3schools.com/browsers/browsers_stats.asp

    Seems like Firefox succeeded in their campaign (not that I’m complaining)

    So, should web developers begin dropping support on IE6? :D

  26. Robin 16. August 2009 at 23:54

    The reason IE6 is just not going away as it should have done years ago, is because developers keep working their butts off to cater for it. Stop. Think. If we all did not bother to cater for IE6 then ALL the sites would look ugly and the complacent IE6 users would be forced to upgrade. We only have ourselves to blame. Please cease all IE6 compatibility coding or else we will be stuck with it for YEARS to come.

  27. Raven Matt 17. August 2009 at 06:08

    I think designers should stop allowing IT departments to screw the web as a whole. If everyone made a stand IT departments would have no choice but to update browsers because the would receive so many complaints about sites not rendering properly. Well, the sites should be rendering properly, they’re just stuck with a turd browser.

    Seriously, It’s 2009 folks. I know I’m preaching to the choir, but…

  28. hitesh 20. October 2009 at 07:44

    thanks for the tutorial but i was looking something by which on clicking on the navigation bar the annoying dotted borders are not seen. can you please tell me how can these be removed

  29. Joshua Michielsen 27. October 2009 at 14:14

    Use the ‘outline’ CSS property, or learn to code good CSS and usea CSS reset?

  30. Gabriel Silva 11. December 2009 at 19:34

    Best solution so far!

    If you really need to suport IE6, use jQuery.