Create dropdown menus with CSS only

June 20, 2009

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

Let's discuss this on twitter.

30 Comments

  • Allan (June 20, 2009)

    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 …

  • Janko (June 21, 2009)

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

  • Janko (June 21, 2009)

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

  • Chad (June 21, 2009)

    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!

  • Kiplog (June 21, 2009)

    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.

  • Janko (June 21, 2009)

    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 ;)

  • webmasterdubai (June 21, 2009)

    nice and good menu and simple.

  • Davide Espertini (June 22, 2009)

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

  • Mat (June 22, 2009)

    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.

  • Webdesign Meppel (June 22, 2009)

    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.

  • Janko (June 22, 2009)

    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.

  • douglasfugazi (June 23, 2009)

    very nice!!
    thanks for sharing :)

  • aravind (June 25, 2009)

    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

  • mateu (June 25, 2009)

    IE 6 não funciona !

  • jro (June 29, 2009)

    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.

  • Viteb (June 29, 2009)

    Nice stuff indeed! It is truly brilliant idea.

  • duellsy (July 6, 2009)

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

  • James (July 15, 2009)

    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.

  • Terry (August 3, 2009)

    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.

  • Pritee (August 4, 2009)

    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.

  • SI Web Design (August 4, 2009)

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

  • Bradford Sherrill (August 4, 2009)

    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.

  • Christhebliss (August 4, 2009)

    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.

  • M Hussain (August 7, 2009)

    Thanks for a nice article

  • Azza (August 14, 2009)

    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

  • Robin (August 16, 2009)

    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.

  • Raven Matt (August 17, 2009)

    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…

  • hitesh (October 20, 2009)

    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

  • Joshua Michielsen (October 27, 2009)

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

  • Gabriel Silva (December 11, 2009)

    Best solution so far!

    If you really need to suport IE6, use jQuery.