Suckerfish Dropdowns

A note from the editors: While innovative for its time, this article no longer represents modern best practices.

“DHTML” dropdown menus have notoriously involved nasty big chunks of JavaScript with numerous browser-specific hacks that render any otherwise neat, semantic HTML quite inaccessible. Oh, the dream of a lightweight, accessible, standards-compliant, cross-browser-compatible method! Enter Suckerfish Dropdowns.

Article Continues Below

Meet the markup#section2

To start, we should use the best method for defining a navigation menu — a list. For this example, we will work on a simple HTML unordered list. {Line wraps are marked ».  –Ed.}

    <li><a href="">Blackbanded»
    <li><a href="">Shadow bass</a></li>
    <li><a href="">Ozark bass</a></li>
    <li><a href="">White crappie</a></li>
    <li><a href="">Smallmouth grunt
    <li><a href="">Burrito</a></li>
    <li><a href="">Pigfish</a></li>
    <li><a href="">Whalesucker</a></li>
    <li><a href="">Marlinsucker</a></li>
    <li><a href="">Ceylonese remora</a></li>
    <li><a href="">Spearfish remora</a></li>
    <li><a href="">Slender suckerfish</a></li>

Quite straightforward really — nice and neat HTML that, as a result, is highly accessible. But now we want to transform this into a dynamic list — the first level of list items will make up a horizontal menu bar from which the second level lists will drop down.

Styling it#section3

To get started, all of the lists need to be jigged around a bit — namely, the padding and margin set to zero and the list-style set to none:

ul {
  padding: 0;
  margin: 0;
  list-style: none;

Now we need to transform the first-level list into a horizontal menu bar. There are a number of methods to do this, discussed in detail elsewhere. We could display the list-items inline (display: inline), but for this example, we are going to float them to the left.

li {
  float: left;
  position: relative;
  width: 10em;

The position has been set to relative because we want the position of the second-level, nested lists to be relative to the first-level list items and the width has been set to space it out a bit. The dropdown menu is coming together.

The next step is to tackle the second-level lists that will be the dropdowns themselves:

li ul {
  display: none;
  position: absolute; 
  top: 1em;
  left: 0;

This positions the second-level lists absolutely (pulling them out of the flow of HTML into a world all of their own) and sets their initial state to not be displayed. If you substitute display: none with display: block, you will see the need for the top and left properties in Internet Explorer, because without them, IE will align the second-level lists to the top right of their relative parent rather than the bottom left. Unfortunately, this IE fix will mess things up in browsers like Opera, so add the following CSS to reset the top and left properties on all but IE browsers:

li > ul {
 top: auto;
 left: auto;

And now, making the sucker work. To make a second-level list appear when its parent list item is “rolled over,” we simply need to add the following:

li:hover ul { display: block; }

Which says that any list that is nested in a list item that has the cursor hovering over it should be displayed.

Finally, because the lists are floated left, the content underneath it needs to be set free of the floating by applying clear: left to it.

Hold on a minute!#section4

“This dropdown malarkey doesn’t work!” I hear 102.6% (or the latest percentage being thrown about) of you cry.  I am, as some might have guessed, talking about Internet Explorer users. The more you use and develop with browsers such as Mozilla the more you realize how pathetic Internet Explorer can be when it comes to web standards. The :hover pseudo class should work with any element, but in Internet Explorer it only works with links. So. What’s the use in a dropdown menu when it only works on -2.6% of browsers? Not much, to be honest. We need to apply a little bit more magic.

DOM-based scripting to the rescue#section5

We’ve established IE’s lack of support for the :hover pseudo class, but by using the Document Object Model, we can attach mouseover and mouseout events to any element. This is good news for us because it means that with a simple snippet of JavaScript we can effectively patch IE’s :hover problems.

Because IE is blind we need to find another way to identify the properties of the :hover pseudo class. With JavaScript, we know that we can manipulate the className property of an element so what we are going to do first is alter the CSS:

li:hover ul{ display: block; }


li:hover ul, li.over ul{ display: block; }

Now we can invoke the :hover CSS rules by adding the class over to the desired element. We also need a way to tell IE which of the UL elements on the page we actually want to be our dropdown menus. We can do this by giving an id to our root ul element:


    Now that we have a means of identifying the root ul element of our dropdown list, we can grab this element and loop through all of its child elements, attaching mouseover and mouseout events to all the li elements nested within it. And this is how it’s done:

    startList = function() {
    if (document.all&&document;.getElementById) {
    navRoot = document.getElementById("nav");
    for (i=0; i<navRoot.childNodes.length; i++) {
    node = navRoot.childNodes;
    if (node.nodeName=="LI") {
    node.onmouseover=function() {
    this.className+=" over";
      node.onmouseout=function() {
      this.className=this.className.replace(" over", "");

    On page load, the startList function is invoked.  The function determines if the browser is actually IE 5 or greater by checking for the existence of the document.all object and document.getElementById function.  This is a bit of a crude way of doing it but it’s short and sweet — and since we are trying to make a compact solution, this will do. It then loops through, enabling mouseover and mouseout events which add and remove the over class from the className property of the element.

    There you have it. If you got lost anywhere, have a look at a commented, bare-bones example  in action.

    Gills, fins, scales…#section6

    So far things are a little bare. The idea has been to show the basic workings of the Suckerfish Dropdown, but CSS can make things look a lot prettier. An obvious starting point would be to apply a background color to the second-level lists.

    After resetting the top and left properties as described earlier, dropdowns in the pretty example appear directly below menu labels in most modern browsers, but unfortunately not in all. In Safari 1.0, they still drop down from the top left edge of the screen. {Check the discussion forum for workarounds. –Ed.}

    Further usability and accessibility#section7

    Making links out of the first-level list items will allow tab-stopping for readers who don’t use pointing devices. Pointing those links to higher-level pages than the links in the dropdowns would be even better.

    About the Author

    Dan Webb

    Dan Webb is a web developer and wannabe DJ. His recent work includes implementing standards-based, accessible sites and web applications for UK government bodies and making people dance around in murky London bars.

    Patrick Griffiths

    Patrick Griffiths is a freelance webmaker based in London who has a penchant for soul music, evolution and walking his pet website, HTML Dog. He sometimes prefers the moniker PTG, depending on what mood he’s in.

    128 Reader Comments

    1. A nice example of drop down menus – probably the most semantically correct bug free version yet. But it still has it’s bugs…

      Ah, for a world where we didn’t have to work around the bugs of useless browsers!

      Might just consider this for one of my future projects – and it’s certainly better than any of the javascript/dhtml versions.

    2. …works fine. At least, it does in version 1.1 (comes with OS X 10.3). I agree that it’s broken in version 1.0.

      The good news is that this means Apple are addressing all these incompatibilities that are being reported…

    3. I still have 10.2.8 on my work system and as such Safari 1.0 and the drop down menus appear in the upper left hand corner of the screen. On my other system I upgraded to Panther and it has a newer version of Safari which works perfectly.

      I wonder if we need to keep an older version of Safari for testing purposes as some people may not upgrade immediately? The more the merrier as far as browsers is great but just makes our jobs as designers a little tougher.

    4. As we learned in the previous issue, display: none effectively hides the content from the screen readers. So is this TRULY accessible or are the screen readers only going to get the top level items and not the secondary items?

    5. Finally a dropdown that looks great and works great. Good article on the technique.
      Is there any way to go and create decendent lists from the child list?

    6. Darn! Why wasn’t this published a month ago?

      I ended up coming up with a similar method for a redesign project at work, though I used mouseover methods on the URLs rather than DOM coding. This is cleaner, though.

      Hmm. May be time for me to recode. 😉

      If IE/Win is your only concern (and not Opera or IE5/Mac, say), and you aren’t a Javascript language purist, you can do a slightly simpler script with conditional comments and DHTML behaviors. But of course, that doesn’t get you compatibility with as many browsers.

    7. As Blakems just mentioned above we are working on getting further nested levels in the dropdowns now and have gone most of the way to making this work.

      The javascript patch for IE is simple enough, it just needs to recurse through any child nodes to attach the behaviour. However, the CSS is another thing…

      We’ll keep you posted. Any ideas greatly appriecated.

    8. Andy, as I understand it (and I don’t have much experience with screen readers, so I may be wrong here), the submenu items probably won’t be accessible as-is.

      If any of the screen readers support Javascript, you could also add an onfocus handler to the script code, which would allow the menus to expand on tab selection as well. The HI of that is a little odd, but it seems possible. Of course, I don’t know that any screen readers would support this in any case. Joe?

      But at least on the sites I’ve worked on, dropdown menus are frills. They save you a step in your navigation, but if your top-level categories are intelligently designed, that’s all they get you–the top-level category you need is hopefully obvious, and when you follow the top-level link, the subnavigation will probably appear early on the index page anyway.

      So I don’t know. I’m something of an accessibility (and standards) advocate, but I’m also a pragmatist. And I’d rather have pretty-good accessibility than none, particularly if the differential is small, and perfection is unattainable.

      Of course, since I’m arguing that dropdowns are optional, it might be more equitable to have *no-one* get to have dropdowns, since after all, they aren’t really necessary.

      I guess my question becomes “is the utility of dropdown menus for your audience such that it’s acceptable to offer them to only part of that audience?” And I can’t answer that for you. …It might be the client’s call in a lot of cases, anyway.

    9. Actually, We experimented using onfocus and onblur to enable mouseless use but I found this was not going to work easily as you cannot attach onfocus and onblur methods to list elements.

      But yes, as you said above Stephen, the objective was to create a simple but effective solution to the problem with the minimum amount of code.

      I also have always used dropdowns as an optional quick route in to deeper content that is always backed up by traditional navigation and this was designed to do that at the minimum of disruption and extra page weight.

      In my opinion, adding a few extra CSS rules and a few lines of JavaScript does mean that giving an optional extra navigation feature to users that can (and want) to use it comes at a much more acceptable cost.

      And yes, clients love this kind of thing..what can you do?

    10. I just tested the bare-bones version in JAWS 4.5, and it worked beautifully. JAWS read the menus as normal lists and sublists. The links were also available via the List Links command (Insert + F7), commonly used by users to cut to the chase.

      I see no problems with this drop-down menu approach and JAWS 4.5.

    11. The fallback option for non-css browsers is clear: plain HTML.

      What about IE with JS deactivated?

      That’s 13-15% of all users, a group too large to get served plain HTML.

    12. Making the dropdown titles link to a certain section will mean those users won’t get the full multi-level functionality of the dropdown menus but they will have single-level navigational menu.

      If they are used as an extra navigational tool (as discussed), they can simply be seen as a bonus to those with scripting capabilities rather than a detriment to those without.

    13. When I went to the pretty example, with the OSX like drop downs with the latest IE6 on XP, the menus “flash” as I mouse between options. What happens is that the background (the light gray lines) disapears and then reloads. It’s really annoying. I checked in Opera and it was (predictably) smooth, so is there any idea why this is happening for IE6?

    14. I have seen this display bug a lot in old versions of mozilla and netscape 7, but never in IE although I have seen many others.

      In netscape/moz the problem was always to do with using ‘visibility:hidden’ or ‘display:none’ to hide menus with anchor tags. The solution was to position the menu ‘off-stage’ when in it’s off state – simply done by changing the positioning value to something like ‘top:-100px’. In this way you never need to change the visibility or display states so it works around the bug.

      I have IE6 on XP and I see no problem whatsoever by the way, but if you think it is a problem then try my suggestion as a bug fix.

    15. Thanks for a clearly written article with clean, compact standards-compliant code. Very well done.

    16. Dan

      Many congratulations on producing this and circumventing some of the bugs in browsers. I’m going to test it on JAWS next week when I can (Thursday or Friday) so that we can prove its accessibility with users who need this technology.

      Must remember to take biscuits for his guide dog.

    17. Dan, Patrick, congratulations on the good work.

      I’m working on the same thing, and have got pretty far. You can check it out at –

      – it might give you some ideas while you work on nested levels code.

      At first, I was thinking on doing similar to what you did, using CSS at fullest and then compensating for IE’s lack of :hover support.

      I gave that up because of real world usability problems (I’m developing the menu and use it at the same time at the client web site).

      I reverted to larger Javascript use to be able to accomodate problems like:

      – large menu list goes off the visible screen area
      – icon support (item icon and submenu arrow)
      – problems with menu being used in the pos:relative and float:left or right layouts, when in IE you have all kinds of overlapping.
      – easy switch between vertical and horizontal use

      Part of these problems and how I solved them can be seen in the three posts I have at the address above. I plan to add another post with some new tweaks I dealt with, this weekend.

      Also, as the menu is used on the bookmaker’s web wite with lots of forms, I added the code that deals with windowed controls punching through the menu layers.

      Feel free to use any of the code in your future work (which I assume is GPL or CC based), as I will certainly review my code based on what you two published here and possibly simplify it.

    18. Some of the problems you mention could actually be solved with CSS:
      icon support by using backgound images,
      IE problem with position and float with the the li > ul bit mentioned in the article,
      horizontal display using position or display properties.

    19. I tested it in Opera and it worked fine. It was the latest version (7.2 I think). Maybe it messes up in earlier versions.

      Is it the examples that don’t work? What happens?

    20. I havn’t tested it but if “display: none;” causes the content to be hidden from some text-readers, maybe a “overflow: hidden;” and “clip: rect(0,0,0,0);” could be used to hide the sub-menus, and then set “overflow: visible;” to show it for the hover state.

    21. LazyJim

      I played around with overflow and clip and came up with

      which does the overflow thing, but sets height to zero rather than using clip.

      It seems to work in IE 6 Win, Mozilla 1.5 and Opera 7.2.

      I would be really interested to find out what the results are of this overflow method compared to the display method in screen readers, which I unfortunately don’t have access to right now.

    22. As previously stated, it’s not working in Opera 7.20. Javascript is enabled, there are no javascript errors, I’m on the normal page’s stylesheet.

      Version 7.20
      Build 3144
      Platform Win32
      System Windows XP

    23. Same here, Opera 7.20, xp, build 3144, javascript enabled, still doesn’t work. Elmo still sad 🙁

    24. First of all thank you very much for this solution. Unfortunately, I’m still at that stage were I’m not sure if it’s me or the browser when it comes to quirks.

      I’m scripting my student government website and have been waiting to ditch the milonic menu system (an abysmal piece of dhtml hackery). Anyway, it seems to be working fine in Moz 1.5, Firebird .7 perfectly.

      I’ve hit a minor snag in safari 1.1 where leaving the menu doesn’t hide the dropped menus. But I’ll chalk that up to safari seeing as it’s lagging simply refreshing simply color change hover events in the menu.

      Moz 1.6a works fine for the most part but only the first few options within the dropped menus are selectable, mousing further down the list causes it to hide as if you intended to leave the menu. Again I’m chalking this one up to the browser and the alpha status.

      As far as IE 6 it begins by not showing the drop downs If I use the selector

      #nav li ul { /* for second-level lists */ or
      ul#nav li ul { /* second-level lists */

      I can’t afford to simply use li ul as I do have other sub lists and I figured this was the easiest way to get around applying style to other innocent elements.

      Additionally, IE seems to be adding a margin or a border to each li item in the sub list if I do use the general li ul selector where it will work.

      I’m really desperate for some help as sadly I’ve had to do this site form scratch by myself with some help from one of my friends back home, troubleshooting these things is becoming tedious (not that you’re strangers to that). If anybody has any suggestions for this scenario I’d love to hear them. Additionally, if you happen to notice any other problems that’d be cool to.

    25. Isn’t there a much easier way of doing this?

      ul li a {
      display: block;
      width: 100%}
      ul li a:hover ul {
      display: block}

      Works in my experience.

    26. Great technique. Just what I was looking for. As for the Opera comments, I’m using the still unoffical build 3221 (version 7.22 on WinXP) and it works fine…

    27. > Some of the problems you mention could
      > actually be solved with CSS…

      I do use CSS as much as possible – DOM is used purely to position elements where needed.
      I don’t see how to control whether is menu going off the visible screen area, using CSS. You need to know how large your menu is, what is available client width etc.
      As for multiple levels, I always wanted as simple code as possible, but as soon as I got into advanced features, I inevitably enter the realm of heavy DOM use.

      If one have multiple nested lists, using

      li:hover ul { display: block; }

      will show all of them, not just first sub-level. You can’t use

      li:hover > ul { display: block; }

      either, because UL is not the first child (it’s plain text node or A element).

      > IE problem with position and float with the
      > the li > ul bit mentioned in the article

      I’m not sure what you mean?
      I’m speaking about the problem explained here: – not sure whether li > ul can help to overcome that problem…

      I have finished, clean script that solves all the problems (except accessibility 🙁 ) and I will publish it on my web site, but I’m not as nearly satisfied as I want to be. It requires each list item to be A element.
      I find that too restrictive, so I’m working on revised code, partially using the code you published here.

    28. I agree that there is a disadvantage of the Suckerfish method in that it can not tell if a sub-menu goes off screen.

      I’m not a big fan of multi-level dropdowns, but it is certainly possible with CSS and Dan and myself intend to tackle it in the near future. It would involve something like displaying the next level (li ul) lists on hover, but explicitly not displaying third level (li ul ul) lists.

      For example, something like:

      li:hover ul {display: block}
      li:hover ul ul {display: none}

      On your other note, the li>ul bit in the article works because IE has a philosophy that children shouldn’t be seen or heard. Everything within the li>ul selector is ignored by IE Win.

      So, the top and left properties are set initially to fix the IE float / position problem and then are reset with the li>ul selector.

    29. I am sorry for not having read the entire discussion, but here’s my bit I developed yesterday without even knowing anyone has been working on it…

      Unfortunately… no way to know weather we are offscreen…

      The multi-nested dropdown UL that works in Moz, Opera and ** (thou shalt not swear). Unfortunately I have to use some browser sniffing for Opera, as it has a rather nasty bug with no workaround…*(It’s stupid, but if you nest an UL inside LI and then set CSS so that UL tries to align with {top: 0} of the parrent, opera will align UL with top of parent’s parent – not LI’s, but UL’s… Really stupid.)

      Also, I have some freakish fancy things done with borders, as it seems, that {border: 1px} confuses the aligns…

      Other than that I use **’s native

    30. No 🙂

      Mike is using DOM scripting to determine whether menu is off-screen.

      There is no way to do it, since CSS is not build to worry about UA size (since for some UAs this is not applicable).

    31. While this method works very well for some browsers, it does not for Netscape 4. It seems that more than a few of the “CSS methods” do not work for Netscape 4. Is this an issue you will address?

    32. As netscape4 is not CSS2 compatible, there is no way this would ever work.
      I am (pesonally) focusing on 2 types of browsers: CSS2 compliant and non-compliant, of which I assume, that the non-compliant one will ignore all CSS.

      There is simply too much legacy browsers to keep eye on them, while trying to make mainstream ones work properly.

      Here’s a bit of a rant to this effect:
      I assume, that anyone using an old web browser has a reason to do so. If the reason is knowledge:

      • I have a dog slow machine
      • I have only alpha numeric screen
      • My IT manager is Hitler, he wont let me install anything
      • I just love this ** 2.1 that came with ******* 95

      I guess they know what they are doing and can turn the broken CSS support off if they want to browse the net.

      On the other hand, if the user is plain dumb, there is no help. If he does not know what year this is, or he can not find his new browser (even though he has been on the net long enough to harbour one of those old browsers) – I have no sympathy for him. Let him think my design sucks, he is of no consequence to anything (ie – can not harm me).

      Sorry about this rant, but I had to do it…


    33. As netscape4 is not CSS2 compatible, there is no way this would ever work.
      I am (pesonally) focusing on 2 types of browsers: CSS2 compliant and non-compliant, of which I assume, that the non-compliant one will ignore all CSS.

      There is simply too much legacy browsers to keep eye on them, while trying to make mainstream ones work properly.

      Here’s a bit of a rant to this effect:
      I assume, that anyone using an old web browser has a reason to do so. If the reason is knowledge:

      • I have a dog slow machine
      • I have only alpha numeric screen
      • My IT manager is Hitler, he wont let me install anything
      • I just love this ** 2.1 that came with ******* 95

      I guess they know what they are doing and can turn the broken CSS support off if they want to browse the net.

      On the other hand, if the user is plain dumb, there is no help. If he does not know what year this is, or he can not find his new browser (even though he has been on the net long enough to harbour one of those old browsers) – I have no sympathy for him. Let him think my design sucks, he is of no consequence to anything (ie – can not harm me).

      Sorry about this rant, but I had to do it…


    34. Oh, the dream of a lightweight, accessible, standards-compliant, cross-browser-compatible method!

      It doesn’t work in Opera 7.20 !

      Dream on…

    35. Netscape 4:
      No, the dropdowns don’t work in Netscape 4. Because the HTML is structured however, if you import the CSS with an @import at-rule, all of the CSS will be hidden from NN4.x and fully functional HTML will remain.
      Personally, I don’t believe anything should be compromised to accommodate NN4 any more. The number of users are tiny and decreasing and the disadvantages of looking after the browser (hacks, heavier pages and the resulting decrease in usability for the majority, alternate versions, resulting problems for mobile interfaces etc.) far outweigh the advantages (erm… NN4 users). And as I said, if things are done right, anything relying on CSS should degrade nicely, retaining completely functional pages.

      Apparently, from what people have said here in the discussions, the dropdowns don’t work in Opera 7.20, but it’s all hunky dorey in 7.21.
      I seem to remember trying this out in Opera some time ago (can’t remember what version – probably 7.something) and it worked when the IE-fix JavaScript wasn’t there.

    36. Obviously, we want this method to work on as many browsers as possible but the point of our method was really that it’s extremely compact and that the markup and execution of the menus mean that they degrade gracefully on most browsers (Currently, the only ones that we’ve encountered that doesnt degrade well are some versions of Safari – which we are looking at).

      For instance, on the versions of Opera that it doesnt work on you still can click on the top level menu items and navigate the site. This to me is acceptible behaviour as the user can still use the site, just not with the quick way in that dropdowns give you.

      While we are working on making it work on as many browsers as possible I don’t think it’s wise to bloat it out too much and lose its simplicity and compactness.

    37. Ignore that previous post. I hadn’t seen the posts that said OP7.20 build 3144 was experiencing the problem (and it is). That link won’t help.

    38. > Left aligned

      This seems to work fine. I checked in Opera 7, Firebird .7 and IE 5 and 6 (on Win).

      In IE4 is not working, meaning that it should gracefully downgrade, which is not.

      In O6 is displaying just the top level, which I gather should be just as fine if each top-level link contains the links to nested items.

      Ideal menu script would be working correctly in:
      – IE5+ (since it is holding overwhelming majority of users)
      – any Gecko or KHTML based browser
      – Opera 7

      For anything else, it should just display the plain old HTML list.

      As for me, this checklist should be working for any styling at all, which is “If you don’t have the latest, your problem” approach.

    39. Yes, I agree. I had to resort to JS to compensate for 2 of the major blunders of **6 browser:

      It does not handle anything but a: hover, so li:hover only works in Gecko.type (G.type) and Opera browsers.

      **6 does not understand the > sign for child UL, so a JS method has to be used to show the hidden UL.

      Both errors are there because of **’s lack of support for standards.

      And in my case I sniff Opera up to compensate for Opera’s bug in formating ‘top’ to parent’s parent.

      So yes.. it’s kinda DHTML, but then againt… it isn’t. It’s like DCSS 🙂

    40. On my version of IE6 Win2K the load time after mouse movement is way to slow to be usable.

      There is a definite pause of a second between when I stop the mouse and when the background loads. If I’m just scrolling up and down the menu I never see the background.

    41. The “flashing” of the menues was addressed in a previous ALA article. Forgive me for not linking, but it was quite recent, since the relaunch. It can be fixed by going Internet Options and having the setting for “Check for newer versions of stored pages” as anything but “every visit to the page”. This allows the background to smoothly pull from the cache and stops the flashing of the background.

      I’ve currently got Opera 7.0 and the menu does not work. They pop up, but without a background image, and when I mouse off of them the menues do not fade gracefully. The leave bits of themselves lying around. I’d be willing to bet it would work fine if the IE javascript work around was removed. Opera’s pickiness over javascript is the main reason it isn’t my default browser. I’m downloading 7.21 now…

      and now Opera crashes as soon as I try to run it so I can see if the upgrade made a difference as far as this code goes.

    42. After uninstalling and reinstalling Opera, the program itself is working once again, and the menues work just fine.

    43. I’m glad for the elegant solution to IE’s problems displaying the li:hover CSS. Thanks.

      But I don’t really understand Javascript, and I’d really like to use this sort of system, but with the current page’s subnavigation expanded by default. I’d like a sidebar navigation, where the subnavigation for the page you’re on begins expanded, and other pages expand on rollover (pushing downward within the same column).

      The page I’m working on does that in Mozilla/Opera/Safari (using the CSS method), but I can’t figure out how to combine what I’m doing (inspired/borrowed from with the Suckerfish methos so it all works in IE (&$*%).

      My testing server is at Has anybody done this successfully? Or is there a simple change to the javascript that would let me recurse through my subnavigation as I’ve got it? Thanks.

    44. I’ve been looking for a while for sometng that does just this (ul/li into a nice nav menu) for my church website. Then ALA pulls one out of the bag! Excellent.

    45. > On your other note, the li>ul bit in the
      > article works because IE has a philosophy that
      > children shouldn’t be seen or heard.
      > Everything within the li>ul selector is
      > ignored by IE Win

      I was puzzled by your response, and couldn’t help thinking that I’m misunderstood.

      So, I’ve taken the pretty example from the article, and enclosed all of the content below the menu into

      Take a look:

      You’ll see that submenu is not displaying at all in Opera 7 or Firebird 0.7, and in Explorer is going below the content of RP div.

      I tackled with this a bit and the solution is:

      Menu itself must be RP with a fairly large z-index, which will put it above anything else and thus allow it to work as needed.
      For this particular example, IE 6 did not show the menu at all, unless its enclosing DIV was absolutely positioned. This is not always the case as I have similar configuration in another project where is working correctly with pos: relative.

      There can be further problems with the pos:relative usage – it all depends where is menu placed. To avoid all problems, its enclosing DIV must be in the BODY. If it’s in some other positioned element, there are certainly cases when this problem can appear again, so this is something to keep in mind.

      Toni’s example is having the sme problem, of course:

    46. This is a very good example, although there are several other solutions to get the second level of the list working under Internet Explorer.

      On a dutch forum (see URL) I saw the following example:

      The solution is pretty simple and working within Internet Explorer. I must say that I did not tested it with (Lorum ipsum) text arround it, so I will mabey have the same problem as Aleksander describes above.

      Tony’s example is nice because he is using an Internet Explorer only feature .htc (HTML Compontens) to get the dropdown list working under IE (because IE only doesn’t support het speudo element :hover). When doing this you don’t let other browsers execute the javascript code. The solutions given to get the list working under Opera 6 is superfluous, because Opera users mostly download the latest version imho.

    47. Thanks Guy’s for the excellent menu and inspiration you have provided. For years IE has made it impossible to do a pure CSS drop down menu now with the help of a minute JavaScript file we can do magic. After reading your article I went ahead and created my own menu which allows multiple levels and a vertical version as well.

      Thanks again for the inspiration.

    48. I put this menu on a test page from my site and strangely, when the menus drop down, they are semi-transparent with the content that appears on the page below the menu. I’m not doing anything in the CSS for the

      below the menus that would account for this, that I know of.

      I’ve tested in Mozilla Firebird 0.7 and MSIE 6, both on WinXP and I get the same behavior in both.

      Any help would be greatly appreciated.

      Thanks, Stan

    49. Aleksandar, the example you give (and describe on your weblog) is very nice and well developed as I say so for myself. But after reading the following articles from PPK (

      Keep CSS Simple

      Keep Javascript Simple

      I thought by myself, isn’t your example having to much Javascript tricks and to much CSS hacks? When I view your source (the html, javascript and CSS source) I must say that there is a lot of code to get something simple working like this.

      The examples which Tony gave in a previous posting and the referral that someone else gave to a script made by Peter Nederlof look much more ‘simple’ than your example. Maybe this is worth thinking about this.

    50. > I thought by myself, isn’t your example having
      > to much Javascript tricks and to much CSS
      > hacks? When I view your source (the html,
      > javascript and CSS source) I must say that
      > there is a lot of code to get something simple
      > working like this

      It all depends on what you want and need. I’m using this throughout the client’s web site, where I can have one or two menus on the same page (Stan James example).

      Site spec is such that I can either use DOM+CSS menu or select list. And I utterly hate the site of drop-down box in the middle of top navigation (not to mention what client thinks of that).
      Also, that is bookie web site with lots of forms and 1 to 3 drop-downs at the page top, just below top nav. If it wasn’t for the WCH (script that hides windowed controls) I would be doomed to show/hide, as StanJames’s current site works.

      So, for me – no, this is just fine. Actually, excellent. Compared to previous menu script used (with tables and lots of browsers tweaks) this code is 3x smaller. (When we finally deploy this new web site, I plan to post a write-up about it, as I think it would be very helpfull for anyone designing something complicated like this).

      > But after reading the following articles
      > from PPK…

      I completly disagree with his article about CSS hacks. But this is not the place to discuss it.
      As for Javascript part, I partially agree, but again – this discussion thread is not about these articles.
      It’s sad the Digital Web is not using blogs for such articles.

    51. > Is there a solution/hack for the problem
      > of dropdowns going behind form controls
      > and Flash content?

      You can have a look at the website of Aleksandar (who has posted more comments within this article).

      On his website you can find the following javascript code which will help you to hide the window controls in Internet Explorer:

      He is also using this for his dropdown menu example:

    52. > Is there a solution/hack for the problem of
      > dropdowns going behind form controls and Flash
      > content?

      apartness already pointed you to the script on my site. For IE drop-downs, that is the way to go.

      If only Flash files are troubling you, then you can save some download time (meaning not using WCH script) if you add this to Flash object tag (or as attribute for embed):

      More details at:

      WCH does not require this parameter – layer will be drawn over flash file in any case.

      Mozilla and Opera 7 can layer-over drop-downs, but I think that they require parameter above for Flash.

    53. Flash is a nasty beast, better avoided than covered with menus. Here’s my “simple solution”* to the problem:

      Sorry about the strange language, though (and yes, the menu doesn’t work in Opera yet… 🙂

      *no flames

    54. Thanks for this article, well written and very useful. I’ve been trying to implement this and have been successful except for one small instance in IE (quelle surprise….)

      In the dropdowns, when I rollover the menu options I’d like to change the background image of the li li object. This works fine in Mozilla using the standard CSS e.g.

      #menu li li:hover, #menu li li.over {
      background: url(../images/global/menu/menu_dropdown_background_on.gif) #ffffff bottom right no-repeat;}

      As you can see I’m trying to get IE to do the same using the .over notation for the top level but it’s refusing to do it. Any ideas ?

    55. I thought, is nested lists the most semantically correct way to do a menu with subs?

      What about two separated lists instead? One with the “main menu” and another with the submenu placed directly under the first?


      • sublink1
      • sublink2

      In that way the most relevant links appears first (semantically speakin) and then the next level.

    56. I’ve ben modding the list to get the design and effects I want. Most of all I want to show the
      list on top and not below the navigation, for that I changed the top: 1em; to bottom: 16px; I use px due to my layout, etc. Now using bottom works perfect in Mozilla and IE but not in Opera 7.23 The list will display on the bottom of the page instead of above the navigation. Does Opera has issues with the bottom property?

    57. Dear group, I have added &nbsp to my lists so the sentence does not break into two lines on my pulldown menus (see below).

    58. What’s&nbspNew
    59. However, this does not validate as XHTML 1.0 transitional (w3c markup validation msg below)

      cannot generate system identifier for general entity “nbspNew”
      reference not terminated by REFC delimiter

      Is there a fix around using the &nbsp character or should I not worry too much abut failure to validate?

      Cheers, Paul

    60. Doesn’t work well for me in IE6 Win 2K. The background colors of the dropdowns in the pretty example flash–sometimes there sometimes not

    61. Paul, check your code – it loks like you have left the semi-colon off the end of the non-breaking space, so the validator tries to read it all as one entity.

      And IMO, trying to make pages validate is A Good Thing. It’s always worth worrying about.

    62. This is a great and easily explained article. Is there a way to have this type of dropdowns that is within a left or right side that when block is shown it pushes everything below down or would this have to be accomplished with Javascript?


    63. Unfortunatly this doesnt work at all in the Konqueror web browser.
      Maybe Im a bit obssesed about this but I realy do make every effort to make my pages work in every possible browser. As you may well imagine this often results in my having to leave out effects that i would like to use. I have yet to find a technique that will produce dropdowns that work well in every browser.

      It’a annoying but i havent found a way round it yet.

      But as a designer im just not prepared to produce pages that wont work correctly in one or more browsers.

      So like i would guess pretty much everyone says; roll on the day for universaly standards compliant browsers.

      If there is a technique that works universaly i would be very interested to know what it is.

    64. Hi,
      thanks for this article, it’s super stuff! I got the menu working (IE5+) and it looks good.

      Now, on our intranet entry page there are three lists of links where a couple of list items in each should have the mouseover function. It sounds worse than it is! I wont start justifying why one would need more than one “navigation” menu on one page, but instead go to the point: how would I make this work? Just pasting the same menu twice on the page won’t work. I suspect the solution is in the javascript – not being very script-literate I would appreciate all help.

      Thank you in advance!

    65. Over at I’ve set up the menus, and they work brilliantly in IE6 and Opera7.

      However, I’ve run into a problem in Mozilla1.5. The restaurant (in the middle) dropdown works well until you hover over an item that happens to be on top of the

    66. I have only recently found out about this site. It is wonderful!

      I have set up a menu on my test server and they work great everywhere except Safari version 1.0. I read the earlier posts regarding this issue.

      I have tried numerous tweaks to get it to work, all to no avail. I am wondering if anyone else has been able to successully get a menu to display properly in Safari 1.0?

    67. I’ve got the drop down menu working fine in IE and Opera, but in Mozilla 1.6a and Galeon, the hyperlinks don’t work. When you do an onClick event, the sub menu disappears but nothing else happens. In Konqueror, it’s even wors. The Drop Down List doesn’t even appear. Any help would be really appreciated as I do want this to work.

    68. I too would love to find a way to make this usable for Safari 1.0 users – even if it was just hiding the submenus. Currently it looks like trash. So sad. 🙁

      All in all, it’s a beautiful menu solution. My favorite so far.

    69. This technique is sooo close. It’s useable, but really difficult to implement with cross-browser consistency unless you tailor your design to accommodate browser quirks and limitations, as your demo does quite effectively.

      But there’s another concession you neglected to mention.

      I’ve noticed that in the markup of the working demo (“pretty” version), the link in each top-level list item is wrapped in a semantically / structurally meaningless set of div tags:

    70. The need for this isn’t explained in the article; but as you evidently discovered, without the extra div all current browsers except ie 5.5 & 6 will insert space after the link when you roll over it — shifting the list-item links following it to the right on mouseover.

      The behavior is unacceptable. But the needless div is also an undesirable compromise.

      If anyone can come up with a better workaraound, please post it here.


    71. when i add this line

      li:hover, li.over ul

      mozilla stops working and when i hover the menu flashes and then it shifts some of the top level elements to the next line.

      Any ideas?

    72. The only the way I can think of to get round the problems of safari 1.0 is to use browser sniffing and then use absolute positioning. However, this totally defeats the whole purpose of using the menu in the first place…any javascript guru’s out there who can know of some other work around?

    73. This is very short and sweet, and I appreciate that.

      Question… isn’t there some way to keep the menus on top/above of other content, like forms and images, instead of the menus hiding underneath them?

    74. Finding this article made me extremely happy, up until I got far in my project and then realized this horrid situation with IE – the drop down menus started flickering everytime my mouse is over them!
      As I went to the suckerfish example I was shocked to find out that they were flickering too.
      Strange, the only thing I did was installing STYLEVISION 2004…

      Any ideas why this is happening?

    75. I found a post here that helped me figure out what was the problem with the flickering effect on IE – it’s the “Check for newer versions of stored pages” set on “Every visit to the page”. If you change that to “Automatically” it will work fine. But this a major setback… Anybody have ideas to fix this bug?

    76. Welll, I don’t like it. A background image for a DHTML Menu is a big no-no. I have built my DHTML menus on simple principles, as can be seen at As PPK noted, A List Apart is nothing more than some childish wow-factor scripts.

      Dante has spoken.

    77. After running this fine menu for a few days, I begain to receive a JavaScript runtime error: “Object Required” on the following element: i */
      startList = function() {
      if (document.all&&document.getElementById) {
      navRoot = document.getElementById(“nav”);
      for (i=0; i

    78. I found the cause of the JS error I mentioned previously within minutes after making the post.

      Funny how that happens so often.

      My .NET page hides the drop-down menus at times, which effectively removes them from the XHTML completely.

      I’m not a JS programmer. Can the JS be modified not to error if no menu is present?


    79. Sometimes old dogs learn new tricks.

      Here’s a revision that doesn’t error out when the menu isn’t present:

      startList = function() {
      if (document.all&&document.getElementById) {
      navRoot = document.getElementById(“nav”);
      if ( navRoot ) {
      for (i=0; i

    80. use the z-index.

      If you set the z-index of your main UL to 2 or 3, it and all its contents (incl. any popup menus) will appear on top of anything else on the page.

    81. That article was the most god-awful piece of crap excuse for a DHTML menu I’ve ever seen. And I’ve seen If you could take your nose out of Mozilla’s ass for just a second you’d see a lot. “Gee. Why not make the CSS work in every browser except the most used one”. It’s like I said:
      “A List Apart is nothing but pages with
      blah-blah wannabe web-developer text that have
      pretty pictures at the top.”

    82. Alrighty. I stumbled across this page last night, and I am happier. I’ve been looking for an ‘easy’ way to do just what this script does.

      But, in trying to make NS7.1, IE6, Opera7.23 happy, I am struggling. I’m in the process of re-laying out my site and need to at least get the top2.htm file right so I can include it across the board. That might be wise, but it’s a work in progress.

      Can someone tell me why my menu is centered in NS, but not Opera or IE? I think it’s a margin issue…

      this be the BSS beast that keeps growing..

      and this is the page:

      as you can see, the pic is centered. the rest ain’t (outside of NS7). I am… perplexed.

      thanks folks

    83. I was working on a DHTML menu when discover this CSS Dropdown and love it. But there’s some things that I wish to know (all about graphical interface):

      1. How to implement a css rollover for the first list and a different rollover for the second one. (I have one working great in Mozilla Firebird but doesn’t work in IE6 and Opera 7).

      2. Is it possible to use this CSS Dropdown menu to make something like the navigation?

      Thanks in advance.

    84. Noemi, thanks for your tip on Z index! I thought it could be done, just didn’t remember the name for it. 🙂

      Now for my next confusion: can these be more than 3 menus/links/divs wide? I noticed the examples using this are just three. Is this because the divs/LIs are float left, none, and right? Could I make more menus by using a table first then put each div/LI in a td and not use the float?

      ..something like that?

    85. I was wondering if anyone tried pre-caching the background image for the drop down menu, as you would for javascript rollovers.

      It would appear that IE is not caching the image, obviously. It is interesting that changing the setting for “check for new versions of cached pages” to anything but “every visit to page” corrects the situation.

      It never was necessary for Javascript rollovers, where you would change the source of the image, once the image was downloaded, it remained.

    86. Let me add my congratulations on this clean solution that works so well.

      With your UL/LI drop down menu in place, is there a way to structure things so that unordered lists in the text below these menus can be presented in its default (or similar to default) format?

    87. I tried two different approaches to this. Maybe you will have better luck than I did.

      First was to give a class (or id) to all the lists used in the menus, with the thought that lists elsewhere in the site wouldn’t inherit the styles for the menus that way. But I didn’t find a way to do that and keep the menus functioning.

      Second was make a standard list class with basics defined, so that other lists on the site would use that class and look as defined. This one didn’t work for me, as my lists were coming from a content editable area, and so users wouldn’t know to add the style.

      Perhaps those will give you some ideas. Good luck.

    88. A Colleague saw this script on this site ages
      ago and sent it to me so that i could try and turn this into a vertical navigation but yet again it’s got bugs! as it doesn’t work properly in IE6 yet it does in all the other browsers that i have tried (can anybody help with this one!

      Test CSS Vertical Navigation

    89. Hi,

      I’ve been playing around, trying to find some way of making the second level be displayed horizontally, and I’ve come to the conclusion that I can’t, at least, not with the Suckerfish and my knowledge of CSS… Any ideas? The problem is that the width of the parent li has to be wide enough to hold all the child lis, but narrow enough to be a tab. Maybe I could slide each tab across, so that they overlap, but then it needs to know which tab it is.


      Will Thompson

    90. Thanks so much for this great tutorial! It’s a holy grail, that’s for sure.

      I’m using the menu system for a design in process, and I encountered something that should be noted for others who also wish to use this system.

      If your menu drops down over any element that is positioned relatively, the dropped down menu disappears behind that relatively positioned element in IE/6 Win, regardless of what z-index you give the menu.

      Thanks again! It’s awesome.

    91. You sholud give a higher z-index and relativ position to the parent element of your menu which is on the same level or higher then other positioned elements.

      [div id=”positionedelement” style=”position:relative;z-index:1″]

      [div id=”menu” style=”position:relative;z-index:2″]

      [div id=”positionedelement” style=”position:relative;z-index:1″]

    92. The menu doesn’t seem to work in Moz/Firebird/Net when you use the “overflow: auto;” css-style on the content below. If you hover over the links with these browsers, the menu hides when you move the coursor over the content below. In Explorer and Opera it works fine…

      Check it out:

      I dont know if its a flaw in the code or the browser… Do you know?

    93. Ok so in the example, the first element in the list has a clickable region that is the entire box, not just the text. The ones bellow the first element in any of the drop downs, has a clickable region of only the text, is there a way to fix it so that all of the links in the drop down have a clickable region of the entire box and not just the text?

    94. Really like the menus, already got plans to implement them in one site, and will be keeping an eye on this site for the more drop down levels. That would make the script excellent.

      Will try and see if I can help out with that.

    95. My menu flickers in Netscape 6.2.3. It seems like the only solution here is to wait for browser updates. Has anyone found an answer to this problem yet?


    96. The Suckerfish example doesn’t seem to work on Netscape 6.2.2 on MacOs9. Has anyone else experienced this? Is it just my machine or is it a problem with that version of the browser? Has anyone found a workaround?

    97. Previous comments have pointed out that there’s a big problem in Safari 1.0, although the dropdowns work fine in Safari 1.1 (apparently, Apple fixed the bug). From reading all the comments, the Safari 1.0 problem seems to be the worst issue with the menu.

      Here’s a workaround. This uses JavaScript to detect Safari 1.0, and keeps the second-level menu hidden from that browser only.

      Insert the following immediately above the tag:

      You could put the JavaScript in a separate file, of course, but the reference to it needs to be located *after* the CSS, in the .

      I copied most of these lines of code from the Browser Detect script by Chris Nott, which is available under a Creative Commons license at

      Note that (1) the version number in Safari’s user agent string is the build number, not 1.0 or 1.1; and (2) I don’t know the correct number to use in the script. 87 may not be the best. All I know is that I’m using Safari 1.0.1 (with OS 1.2.8) and it is version 85.6. I don’t know what version was the first for Safari 1.1. (I didn’t see it in a quick look at Dave Hyatt’s blog.) If someone knows the answer, please post it.

      Using the above code, Safari 1.0.1 displays only the top-level menu with working links, while the dropdown menus work in other browsers.

    98. Corrections: The title of my post should have been “Safari 1.0 workaround” (not 1.1). And I’m using Mac OS X 10.2.8 (last Jaguar version).

      Also note that I’m not a JavaScript wizard, so someone may be able to improve the code.

    99. If someone has a vertical popup/”dropdown” menu that is ready for prime time, I’d love to see it; and use the code, if you’re willing to share.

      I’ve been trying to create a vertical version, where the second-level menus open to the left. After spending a couple days, including looking at a few prominent CSS sites for ideas (including Listamatic), I nearly succeeded, but have given up. From what I can tell, browser support is not good enough yet to implement this on a business web site for a paying client.

      Eric Meyer came close
      But it only works in some browsers, and some important details are not so great (on mouseover, the menu “title” disappears from top-level menu). Not good enough for my needs.

      Given that a CSS-only solution is NOT ready for prime time, I would like to find a JavaScript substitute that meets ALA’s usual criteria: high-quality, high standards-compliance, lightweight, portable, customizable. Of course, it needs to work in nearly all browsers, especially IE/Win.

    100. Is there any way to link to an external stylesheet that will do the same thing? I’d like to use this IE hack, but I’m trying to keep my web pages clean.

    101. Larry’s aforementioned code seems to grab the “spoofed” Mozilla version number (which is “5”) rather than the Safari build number. As a result, using his code appears to disable the drop down functionality for all versions of Safari, not just the pre-Panther versions.

      I managed to cook up the following code which appears to grab the correct build number. Note that Javascript is not at all my specialty, so some of you will undoubtably find “opportunities for improvement.” 🙂

      // Sniff pre v.86 versions of Safari

      var agt = navigator.userAgent.toLowerCase();
      var appVer = navigator.appVersion.toLowerCase();

      var is_safari = (agt.indexOf(“safari”) != -1);
      var build = appVer.substring(appVer.lastIndexOf(“/”)+1);

      if (build < 86) { document.write('


    102. Fixed a couple of problems for you and got it to validate. I got it to work as (I think) you intended in MSIE 6.0, Netscape 7.1, Opera 7.23, Mozilla/Firebird 0.7, K-Meleon 0.8.2. The main to the css changes were:

      li {

      Clear: left;
      float: left;
      clear: none;
      float: none;

      li > ul {
      top: auto;}


      I am still having issues with my site on Mac browsers. Unfortunately I do not have easy access to a Mac so turnaround is slow. If anyone has any advice I would sure appreciate it.
      -William Ellis

    103. dont forget the doctype:

      i was using Transitional and it wouldn’t work in Mac/IE. once i changed to strict, everything worked great.

    104. I’m working on a website for school and my teacher refuses to give up frames. He wants a drop-down menu in a typical side-bar fashion. After trying this example, my drop-downs go outside of the frame so they aren’t much good.
      I was looking at two solutions, and was wondering if anybody here could help me with either of them.

      Solution 1: Code the drop-downs in such a way so that the drop-downs push the lower options out of the way, in the same column. Example(hope this works):

      Heading 1
      Heading 2
      Heading 3

      And when mouse hovers on Heading 2, you get:

      Heading 1
      Heading 2
      Option 1
      Option 2
      Heading 3

      You get the idea, right?

      Solution 2 (may be easier?): His main objections to tables instead of frames is that it’s easier to maintain one menu file. So, I was wondering if it would be possible to add in a special HREF that would embed the code for the menu into the table, without having to copy it again. I hope you can understand what I mean…

      Thanks for the help, and I’m finding this to be a great site for information.

    Got something to say?

    We have turned off comments, but you can see what folks had to say before we did so.

    More from ALA