Introduction

The Suckerfish menu, first published in A List Apart in 2003, was a major achievement. The authors, Patrick Griffiths and Dan Webb, showed how to build a horizontal dropdown menu that was highly cross-browser compatible with very efficient CSS. For browsers that didn't support the "li:hover" (Internet Explorer - IE - 6, of course), the authors provided a JavaScript that made the menu work even there.

Markup (HTML)

A standard unordered list (<ul><li>). It has class="barmenu".

<ul class="barmenu">
<li><a href="#">Link 1</a></li>
<li><a href="#">Link 2</a>
  <ul>
    <li><a href="#">Link 2-1</a></li>
    <li><a href="#">Link 2-2</a></li>
    <li><a href="#">Link 2-3</a></li>
  </ul></li>
<li><a href="#">Link 3</a>
  <ul>
    <li><a href="#">Link 3-1</a></li>
    <li><a href="#">Link 3-2</a></li> 
    <li><a href="#">Link 3-3</a></li>
   </ul></li>
</ul>

CSS (with comments)

The Suckerfish

The logic of the Suckerfish menu has since been used widely to build menus for web pages. The core of it was provided by the authors in a barebones version. The Suckerfish dropdown menu uses the following 5 rules to do the job (I have included their original comments as well):

ul { /* all lists */
	padding: 0; margin: 0; list-style: none; } (Rule S-1)
li { /* all list items */
	float: left; position: relative; width: 10em; }(Rule S-2)
li ul { /* second-level lists */
	display: none;	position: absolute; top: 1em; left: 0; }(Rule S-3)
li>ul { /* to override top and left in browsers other than IE, which 
   will position to the top right of the containing li, rather than
   bottom left */  top: auto; left: auto; } (Rule S-4)
li:hover ul, li.over ul { /* lists nested under hovered list items */
	 display: block; } (Rule S-5)

That's it. Five CSS rules for a dropdown. This was a major achievement at the time it was published - neat, simple, orderly rules and very cross-browser compatible. The question is, can it be improved on now, almost ten year later with more standards-compatible browsers and with IE 6 more or less out of the picture? As of July 2011 it is used by 2.3% of users. And IE7 is used by a little more than 4%!

Modern CSS dropdown - barebones

In the following rules you can take out the ".barmenu" if you want - I just need to use a "class" here because I have other menus and other unordered lists in this blog, so that I need to use more specific rules.
.barmenu ul, .barmenu li { /* all lists */
   padding: 0; margin: 0; list-style: none; } (Rule 1)
.barmenu li { position:relative; float:left; width: 5em; 
   padding:0 0 1px; } (Rule 2)

I usually style the link element rather then the <li>, but since I don't style I simply give the <li> a width here. This should go out when the menu is styled. The strange padding is explained below (under Rule 4).

.barmenu li ul { position:absolute; visibility:hidden;
    top:20px; left:0; }(Rule 3)

I usually use "visibility: hidden" and "visibility: visible" to hide and unhide the dropdown. "Visibility" was introduced in CSS2 and is well supported today. I could also have hidden the dropdown outside the viewport, positioning it absolutely at -999em, which today is another standard method. As it turns out, both ways of doing it encounter exactly the same problems in IE.

"top" and "left" above are needed for IE7 and IE8, the modern browsers (Opera, Chrome, Firefox, and Safari) do not need them. The modern browsers seem to assume "left:0" and a vertical offset equal to the current line height - both reasonable assumptions. IE, on the other hand, assumes 0 vertical offset and a default margin <ul> or <li> offset, which simply is odd.

.barmenu li:hover > ul { visibility: visible; margin-top:-1px;
    background: #FFF; }(Rule 4)

This rule makes the child elements of a <li> visible when <li> is hovered. Note that "visibility:hidden" reputedly leads to "performance problems" in IE7 and IE8, while the modern browsers seem to handle content hidden with "visibility: hidden" quite well.

However, it also contains two "fixes" for IE7 and IE8. The first is "background: #FFF". This is not included to give a background (I use white - #FFF - here anyway, so the menu inherits that) - it is there to make the display of the dropdown stable and scrollable in IE7. Without background the submenu appears as long as the mouse hovers over the parent menu item, but once you move the cursor down over the submenu, the submenu disappears. This is not what we want.

I have spent many hours tesing various fixes to this. The usual fixes for IE problems, such as "zoom:1" or "height:1%" don't work here. But background does - either a color or a background image. Omer Greenwald at webtechwise.com uses a transparent background image as a fix, and that seems to work just as well.

The other fix used here, which also seems to be required for IE7, is to make certain that the top menu and the dropdown actually "touch" one another. If there is a one pixel gap, the dropdown will disappear when you move the cursor down and over the "gap" to click the submenu items. The fix for this is to include a padding of 1px at the bottom of the <li> (Rule 2) and then use a negative margin of 1px to move the dropdown up into the top menu (Rule 4).

It is somewhat interesting to note that if you move the dropdown a little to far down - for instance "top:25px" - the problem returns.

Note that most of the fixes for IE used here are specific to a barebones menu. Once you style the menu, the dropdown is likely to actually touch the top level menu, so that problem disappears. And when you give color to the background - which you probably will - you take care of that issue too.

OK. That's it. One rule less than the Suckerfish menu, and we don't need any java if we don't support the soon to be gone IE6. It works as intended in all major browsers as well as IE8 and IE7. To make it work in IE6 will require rewrites, as IE6 does not support the child selector > that I use here. It will also require JavaScript as IE6 only supports the hover property on links, not on lists and other elements.

Here's the menu:

So that's it. Four CSS-rules for a dropdown menu - and one of the rules a reset rule (Rule 1). That's all we need with modern browsers! But then, of course, lots of fixes for the older versions of Internet Explorer. What a waster of web designer man hours those browsers have been.

(Revised 9/23/2011: Edited Rule 4: .barmenu li:hover > ul changed to .barmenu :hover > ul.

Basic styling

Usually one styles the links rather than the <li>-items. The advantage is that this was one increases the clickable area of the menu. The <li>-items don't need styling - they simply adapt to the space requied by the content. I need to use a different class, as I display both menus here.

.barmenu2 a { display: block; width: 5em; color: black; line-height: 25px;
   text-decoration: none; background: silver; text-align: center; } (Rule A)
.barmenu2 a:hover { background: #7B7B7B; color: yellow; } (Rule B)

And that's all. So now I can remove the various fixes (in Rules 2-4) from the barebones example. The only ones I still need are "top:25px" (adjusted to 25px as that is the height now) and "left:0". I've also taken out the width in the <li>-rule:

.barmenu2 li{ position:relative; float:left; } (Rule 2)
.barmenu2 li ul { position:absolute; visibility:hidden; top:25px;left:0; } (Rule 3) 
.barmenu2 :hover > ul { visibility: visible; } (Rule 4)

(See revision of Rule 4 above.) If you want to style the dropdown, you can use:

.barmenu2 li ul a { something .. }, and
.barmenu2 li ul a:hover { something else } (for the hover)

A useful tip on styling menus with hidden dropdowns or flyouts is to simply comment those parts that hide it out and style the menu with the whole menu visible. Here that would simply mean to comment it out like so /* visbility: hidden; */ in Rule 3. When done, you simply remove the comments.

OK. Here is the menu:

So there it is with some basic styling. Now it works just fine in all browsers, including IE7 and IE8.

Please support

Blogging and web design is my living. Even though I give this away for free, it has taken me a long time to develop, test and write up.

So a donation would be very welcome, especially if you are going to use the code or have learned something reading this.

Nekkidblogger needs
your support! Thanks!!