TJKDesign: Home Page
Creative Commons License
This work is licensed under a
Creative Commons License.

If you've found this beneficial, consider making a donation through Paypal

Guild of Accessible Web Designers Logo
Valid XHTML 1.0!
Section 508
Web Standards
Tables-less Layout
Frames: a solution or a problem?
XML Feed
NN4.7 Safe!

TJKDropDown Menu

The Magic...

The following rule uses the pseudo class :hover on a li. This is perfectly kosher; the only problem is that MSIE is ":hover-challenged". The only time this browser gets it right is when it is associated with anchors (as in a:hover).
NN6 and Opera 7 do not behave much better. To "pop up" the ULs with these 2 browsers the user needs to hover over the bottom right corner of the top level links. See figure A:

#zUL li:hover ul {
visibility:visible;
background-color:#fff;
}

The purposes of these declarations:

  1. We make the nested element visible,
  2. We set a background color for that element,

If you have a decent browser, you can already give it a try.

Take note This article is from 2003; the technique described here is deprecated as it is not reliable with modern browsers (IE 7 and FF 2.0).
Check my latest article about pure CSS drop down menus for a better solution.

Figure A

Qui in ea voluptate sed ut perspiciatis unde omnis ullam corporis suscipit laboriosam. Qui ratione voluptatem sequi nesciunt. Dicta sunt explicabo. Omnis dolor repellendus. Nisi ut aliquid ex ea commodi consequatur? Et expedita distinctio. Id quod maxime placeat facere possimus, sed quia non numquam eius modi nam libero tempore. Consectetur, adipisci velit, dicta sunt explicabo.

This is a list of our problems so far:

  • MSIE does not reveal the nested elements,
  • NN 6 and Opera7 do not either,
  • NN 6 doesn't not apply the background-color to the nested ULs,
  • NN 7 and Mozilla display the sub links next to each other, on one single line.

Our plan B (to reveals the sub links) is to use CSS with some JavaScript. Thanks to the DOM, we can use the className attribute to "toggle" the class value of the elements. So we create a class that we append to the HTML selector (li). Our last rule becomes:

#zUL li:hover ul,
#zUL li.msieFix ul {
visibility:visible;
background-color:#fff;
}

We then add in the markup 2 JavaScript events with a short statement (inside each top level LI tag):

<li onmouseover="this.className='msieFix'" onmouseout="this.className=''" ><a href="#">1st Set of Links</a></li>
<li onmouseover="this.className='msieFix'" onmouseout="this.className=''" ><a href="#">2nd Set of Links</a></li>

The purposes of these events:

  1. When the cursor hovers over one of the top level LIs, the class msieFix is assigned to the element and it triggers the rule, popping up the nested ULs.
  2. When the cursor moves away from that link, we reset everything.

You can see in figure B that even if we've fixed browser's lack of support for the :hover pseudo class, we still have work to do:

  • In MSIE, z-index didn't take care of the problem related to the stack order and the elements' position is wrong,
  • In NN 6 and Mozilla, the anchors in the nested ULs are still on one single line.
Figure B

Qui in ea voluptate sed ut perspiciatis unde omnis ullam corporis suscipit laboriosam. Qui ratione voluptatem sequi nesciunt. Dicta sunt explicabo. Omnis dolor repellendus. Nisi ut aliquid ex ea commodi consequatur? Et expedita distinctio. Id quod maxime placeat facere possimus, sed quia non numquam eius modi nam libero tempore. Consectetur, adipisci velit, dicta sunt explicabo.

Fixing MSIE first:

* html fieldset p {z-index:-1}
* html #zUL li:hover ul,
* html #zUL li.msieFix ul {
top:1.1em;
left:.2em
}

The purpose of these rules:

  1. Trying to bring the nested ULs "in front" with z-index fails with MSIE, so it is the paragraph that we are "moving down" the stack,
  2. To fix our positionning problem we can simply take advantage of the position:absolute declaration we used earlier for the nested ULs and give these elements a X and Y reference.

Take note We use the star html selector to make sure only MSIE applies these rules. Other browsers are smart enough to know that HTML is the root of the document and has no parent, so they will ignore the rules. You could think that the second one is harmless, but it is not for NN6 and Mozilla.

Figure C

Qui in ea voluptate sed ut perspiciatis unde omnis ullam corporis suscipit laboriosam. Qui ratione voluptatem sequi nesciunt. Dicta sunt explicabo. Omnis dolor repellendus. Nisi ut aliquid ex ea commodi consequatur? Et expedita distinctio. Id quod maxime placeat facere possimus, sed quia non numquam eius modi nam libero tempore. Consectetur, adipisci velit, dicta sunt explicabo.

Taking care of Mozilla, NN 6 and NN 7 all at once:

#zUL li ul li {background-color:#fff}
#zUL li ul {
visibility:hidden;
position:absolute;
width:9em
}

The purpose of these rules:

  1. The first rule helps NN6 (and Opera 7 to some extend) to paint a background behind the anchors. This browser doesn't render the background color of the ULs, so we set a background color for the second level LIs instead,
  2. The width declaration in the second rule is what put all the sub-links in one single column (NN 6, NN 7, Mozilla).

Take note To simplify, but mostly to avoid redundancy, we would remove the background declaration from the rule with the nested ULs for selectors using only that one, for the purpose of showing links over a solid color background.

Figure D

Qui in ea voluptate sed ut perspiciatis unde omnis ullam corporis suscipit laboriosam. Qui ratione voluptatem sequi nesciunt. Dicta sunt explicabo. Omnis dolor repellendus. Nisi ut aliquid ex ea commodi consequatur? Et expedita distinctio. Id quod maxime placeat facere possimus, sed quia non numquam eius modi nam libero tempore. Consectetur, adipisci velit, dicta sunt explicabo.

From there, one can chose to spice up the menu or, better, try something a bit different...