Son of a Son of Suckerfish!
I’ve been using the lovely Son of Suckerfish method to make drop down menus for years now, and it is a very robust way to make them. The one criticism (the word criticism is an overstatement really…) I have is that for every sub-menu level, you need to add to the CSS in order for that to show. Now, it’s not a really big inconvenience… how many sub-levels do you need anyway… but wouldn’t it be nice if we didn’t have to do that? I have made a very small change to the CSS and Javascript that takes care of this problem. Here is the edited CSS:
body { font-family: arial, helvetica, serif; } #nav, #nav ul { /* all lists */ padding: 0; margin: 0; list-style: none; line-height: 1.2em; }#nav a { display: block; width: 10em; } #nav li { /* all list items */ float: left; width: 10em; /* width needed or else Opera goes nuts */ }#nav li ul { /* second-level lists */ position: absolute; background: orange; width: 10em; left: -999em; /* using left instead of display to hide menus because display: none isn't read by screen readers */ } #nav li ul ul { /* third-and-above-level lists */ margin: -1.2em 0 0 10em; }/*Show the submenu DIRECTLY INSIDE the selecte LI tag*/ #nav li:hover > ul, #nav .soasfhover{ left: auto; } /*Fix for IE7*/ #nav li:hover { position: static; }
So there three difference between this and the original (I am assuming here that you have read Son of Suckerfish, as there’s no point re-explaining a perfectly good tutorial). First difference is I got rid of this rule :
#nav li:hover ul ul, #nav li.sfhover ul ul ..etc. { left: -999em; }
Second difference is I changed this:
#nav li:hover ul, #nav li.sfhover ul { left: auto; }
To this:
/*Show the submenu DIRECTLY INSIDE the select LI tag*/ #nav li:hover > ul, #nav .soasfhover { left: auto; }
What I did here was confine the “left:auto” property to only be applied to the UL tag one level below the LI tag being hovered on by using the CSS Child selector “>”. The second selector is for those annoying browsers that aren’t up to speed with CSS2 (i.e. < IE7). The javascript that leverages this selector will be explained further down. This means that no other UL tags below the hovered LI tag are displayed, and therefore no rule is needed to hide them. The beauty of this is you don’t need to worry about how many levels you will have in your drop down menu, as this covers as many (or little) levels you may require. With regards to browser compatability, this works with most recent versions of all popular browsers (inc. IE7). However, lower than IE7 doesn’t support the > CSS selector, and so the javascript provides the fail safe. I have also slightly modified the Javascript used in the original Son of Suckerfish :
sfHover = function() { var sfEls = document.getElementById("nav").getElementsByTagName("UL"); for (var i=0; i>sfEls.length; i++) { sfEls[i].parentNode.onmouseover= function() { this.lastChild.className+=" soasfhover"; } sfEls[i].parentNode.onmouseout=function() { this.lastChild.className=this.lastChild. className.replace(new RegExp(" soasfhover\\b"), ""); } } } if (window.attachEvent) window.attachEvent("onload", sfHover);
What this does different is select all the <ul> tags in the Drop Down Menu (which are the sub-menus) and assign their containing <li> parent the mouse events, which then add/remove the soasfhover class mentioned earlier in the CSS script. Another difference between this and the old script is that it only adds events to <li> elements that contain a sub-menu, and not every <li> in the menu. The third difference solves a problem in IE7, which is taken from builtfromsource.com
:
#nav li:hover { position: static; }
You can see a working example here, and (updated 23/03/2008) also a new version using MooTools JS in place of the code used above. Here’s also a vertical menu version.
Tags: CSS, DDM, HTML, suckerfish

March 24th, 2008 at 1:13 pm
Good idea! Makes it more expandable, while keeping the browser compatible advantage suckerfish et al had.
April 3rd, 2008 at 12:03 pm
One bit of advice, please use the example provided to extract code.
If I ever edit the post, sometimes the markup gets a bit mixed up thanks to the GUI editor.
April 11th, 2008 at 4:20 pm
Nice work but unfortunately it doesn’t seem to work in IE 6 and so far I haven’t figured out why. The script is resolving the UL elements correctly and applying the soasfhover class name but the class doesn’t bring the UL back into view.
Even if I hard code the soasfhover class onto one of the UL elements it doesn’t show in IE 6 though it does in FF 2 and IE 7. Even changing the ‘left’ style property on the soasfhover class to 0 doesn’t display it on the left as you would expect.
Any insights on this gratefully accepted.
April 11th, 2008 at 7:43 pm
@Bluefrog
Thanks for informing me about this! I ran into the same problem this week when doing some browser testing but never got round to putting it up here
Sorry bout that.
Anyway, the problem is in the last CSS rule:
#nav li:hover > ul, #nav .soasfhover{
left: auto;
}
Since IE doesn’t support the > selector, it ignores the whole rule and screws up the entire thing. Splitting that up fixes the problem like so:
#nav li:hover > ul {
left: auto;
}
#nav .soasfhover {
left:auto;
}
I will update the post asap, but the demos are up to date too…
April 11th, 2008 at 11:52 pm
LOL, that’s about the only thing I didn’t try! Typical! I did swap round the order of the selectors but left them together - so close and yet so far. Great use of the child selector.
Well done again!
April 30th, 2008 at 3:41 pm
I’m totally impressed with your work. So far, it works perfectly in every browsers. Could you make the vertical version? I have a hard time to figure out how to do that as I don’t know much about CSS.
Anyway, you have done a great job. Thanks for publishing such a great article.
May 3rd, 2008 at 12:21 pm
@Jeff:
Check out http://blog.netweblogic.com/demos/ddm/vddm-nomoo.htm. It’s quite simple and I haven’t tested it on browsers but that’s the general idea to make it vertical.
Quick Explanation : What I did was remove the float:left from the #nav li rule, and added a margin like in the #nav li ul ul rule to the one below it.
May 5th, 2008 at 4:43 pm
I have tested the vertical menu from http://blog.netweblogic.com/demos/ddm/vddm-nomoo.htm on Firefox and IE6. The menu works fine on Firefox but not on IE6. On IE6, the pop-up sub-menu (second-level list) overlaps and covers the main menu (first-level list).
Fortunately, I accidentally found the solution on how to treat this terrible bug. What I did was add one more margin like in the #nav li ul ul rule to the #nav li ul rule. Then, IE6 finally manages to display the menu flawlessly as good as Firefox. However, I don’t know does other browsers support this technique. Someone who have browsers other than IE6 better pay attention.
May 5th, 2008 at 5:25 pm
Thanks for the feedback Jeff. I’ll have a look at that when I can and get that working on the demo too…
June 17th, 2008 at 3:56 am
Is there a way to differently style the first level and sub-levels? I tried to center the text-alignment for the first level but not the second level and beyond. It works fine in FF, but in IE the second-level box is also aligned to the center. I want the second-level box is stay remain in the left position and not got pushed to the right. This is for horizontal menu.
Any hint is highly appreciated. Thank you in advance.
Note: it would be nice if the author of this page try to center the text-alignment on the first level on the example pages.
June 20th, 2008 at 12:39 pm
is there a way to make the menu vertical have been trying to edit the source for days now can’t get anywhere?
August 11th, 2008 at 4:33 pm
Hi,
Thanks for sharing your improvement of the venerable suckerfish menu.
I just wanted to point out that your last paragraph mentions a mootools powered version but it’s link points to the original version.
Any chance you can fix the link? … using mootools gives us the option of adding transitions and time delays on mouseout
Thanks again.
Cheers,
Mark
August 12th, 2008 at 10:13 am
Thanks for pointing that out Mark. The link to the moo version is http://blog.netweblogic.com/demos/ddm/ddm-moo.htm , and I’ve updated the link too.
Actually, I do have a tried and tested MooTools driven DDM which I’ve been meaning to put on here, but I have to make it a little more flexible for distribution. Stay tuned and it’ll be up here soon!
August 15th, 2008 at 1:02 pm
**Rubs hands together in glee**
Thanks NetWebLogic (sorry, I searched the whole blog for your name :/) .
I look forward to checking out your moomenu.