Update: Please note that this content is outdated and should not be considered as best practice.

Dropdown menus are often done with a lot of JavaScript but I wanted to do one using CSS. It is reasonably cross-browser and standards compliant.

Please note that I do not recommend using this kind of menu for public sites, since it is inaccessible for users with CSS turned off and several mobile browsers. Some users also find it difficult to navigate with pull-down menus. If you use this kind of menu on a site, make sure that navigation is possible even without the pull-down.

Having said that, here is an example of how such a menu could look like. Hover the headers below to see it in action.

How is this done? The markup looks like this:

<ul id=”dropdown”> <li><a href=”#”>English</a> <ul> <li><a href=”#”>William Blake</a></li> <li><a href=”#”>Emily Bronte</a></li> <li><a href=”#”>Robert Burns</a></li> <li><a href=”#”>John Keats</a></li> <li><a href=”#”>Percy Bysshe Shelley</a></li> </ul> </li> … </ul>

As you might guess, the technique is basically about nesting UL elements. The first level of list items is the main navigation.

ul#dropdown li { display: inline; position: relative; … }

The second level of unordered lists is the actual drop-down. They are initially invisible, done by setting display:none. They are also positioned absolute.

ul#dropdown li ul { display: none; position: absolute; … }

The second level is displayed on hover using CSS :hover pseudo class.

ul#dropdown li:hover ul{ display: block; }

Unfortunately, IE has lousy support for the :hover pseudo class. So to make it work properly, we have to use a bit of JavaScript to attach mouse-over events to the list elements (thank you, Patrick Griffiths and Dan Webb). Here is one way of doing this:

<script type=”text/javascript”> fixhover = function() { if (document.all && document.getElementById) { navnode = document.getElementById(“dropdown”); for (i=0; i < navnode.childNodes.length; i++) { childnode = navnode.childNodes[i]; if (childnode.nodeName == "LI") { childnode.onmouseover = function() { this.className += " over"; } childnode.onmouseout = function() { this.className = this.className.replace(" over", ""); } } } } } window.onload=fixhover; </script>

The solution also uses the infamous “Holly Hack” in CSS, named after Holly Bergevin. This technique is a method to fix weird rendering bugs in IE6 by triggering hasLayout.

/* Fix IE positioning bug with the Holly Hack \*/ * html ul li { float: left; height: 1%; } * html ul li a { height: 1%; }

As always, there is plenty of room for improvement and this code should only serve as a humble example (for instance, don’t use inline styles and scripts).


No comments yet.

Leave a reply