Horizontal “drop down” menus are familiar to almost every computer user, so they are a natural fit for sites that have many pages organized into seven or fewer categories.
Many web developers assume that creating a drop down menu requires JavaScript or Flash; the reality is that the menu system is merely a nested HTML list, just like those we have created in the past, with the presentation handled by CSS, no JavaScript required.
It should be noted that there are many, many CSS drop down menus out there. The most well-regarded is the “Suckerfish” code, originally developed in an article on A List Apart. The system I am about to describe is an evolution of the ideas expressed in that article, with less vestigial code and fewer concessions to older browsers: thus, “Remora”.
First, the code. Once again, we are using nested lists; as before, you should be careful to ensure that any new lists are contained inside an <li> element with a class of submenu. Each nested list will be a drop-down menu element.
As I am currently residing in Auckland, I will make the drop down menu for a fictional boat-building website:
- <ul id=”nav”>
- <li class=”submenu”><a href=”#”>Yacht designs</a>
- <ul>
- <li><a href=”#”>Sloops</a></li>
- <li><a href=”#”>Ketches</a></li>
- <li><a href=”#”>Yawls</a></li>
- <li><a href=”#”>Schooners</a></li>
- </ul>
- </li>
- <li class=”submenu”><a href=”#”>Small boat designs</a>
- <ul>
- <li><a href=”#”>Skiffs</a></li>
- <li><a href=”#”>Tenders</a></li>
- <li><a href=”#”>Dories</a></li>
- <li><a href=”#”>Canoes</a></li>
- <li><a href=”#”>Kayaks</a></li>
- </ul>
- </li>
- <li class=”submenu”><a href=”#”>Clippers</a></li>
- </ul>
(Note that every entry on the main navigation bar will require a class of submenu, even if it does not contain an actual menu).
Now the CSS. First, we will reset both the list and links, removing all spacing, text decoration and bullets, while specifying a new font. At the same time, we’ll specify that each link in the list will always display on its own line; by doing so, we can also give links a set width:
- ul#nav, ul#nav ul { padding: 0; margin: 0; list-style-type: none; }
- ul#nav a { text-decoration: none; colour: #fff; background: #000;
- font-family: Eurostile, "Square 721", Serpentine, Arial, sans-serif;
- display: block; width: 10em; padding: .2em;
- }
This makes the entire navigation vertical, like our accordion menu example. We want the main <li> elements, the one with a class of subnav, to appear beside each other. We could try display: inline, but that would remove any opportunity to provide them with a width, in the event that we wanted to push the main menu items further apart. Instead, we’ll float them:
- ul#nav li.submenu { float: left; position: relative; }
Note that this will effectively float the entire menu; if you want the menu bar to appear on its own line, there are two possible solutions:
Keep the menu bar at its current length and height and set
clear: lefton the first element that follows it, be it a heading or paragraph.Set a height of
1.8emor so to theul#navlist and add an appropriate background colour. The main unordered list is not floated – it just doesn’t have any height, and therefore does not push around other elements.
To create the “drop-down” effect we need to visually remove the submenu lists from the page. While there are many possibilities for achieving this, the tried-and-true method is to position the submenu lists absolutely, and then to give each list a left position that is far off the screen (we can’t use right, as can never anticipate just how wide a browser might be). When the user hovers their mouse over the parent <li>, we reset that distance to 0:
- ul#nav li ul { position: absolute; left: -999em; }
- ul#nav li:hover ul { left: 0; }
That’s it. I would typically add a little more CSS to make the menus look better, (as you can see in the example above), but the functionality is entirely there.
One final note: it is poor form (not to mention potentially confusing to users) to obscure important information with a drop-down menu. You have a few choices: either apply sufficient margin-bottom to the menu (at least equal to the height of the tallest drop-down element) to push other content out of the way, or apply opacity or rgba values to the drop-downs themselves. I have opted for the latter.
This solution will work in all modern browsers, as well as IE7 and above. IE6 and earlier require a little JavaScript trickery to allow hover behaviours on list items.
Fixed, Cory - thanks for pointing out the error! I'll also expand on this article in the very near future.
Haha, that is actually incredibly clever.
![Prometheus: Collector's Edition (Bilingual) [Blu-ray 3D + Blu-ray + DVD + Digital Copy] Prometheus: Collector's Edition (Bilingual) [Blu-ray 3D + Blu-ray + DVD + Digital Copy]](http://ecx.images-amazon.com/images/I/5192I1rtYnL._SL160_.jpg)

