Reg Exp
Web Design
Notes Client
Accessibility Compliant Drop Down Menus
The new (as of January, 2005) Breaking Par web site uses a drop-down menu to get at the hints and tips categories. Take a look at "Hints/Tips" in the menu options above. When you mouse over "Hints/Tips", the different tip categories appear. This drop-down menu does not use JavaScript (well, almost) and does not use DHTML (well, that depends on your definition). It is accessibility compliant and makes use of style sheet properties to provide the effect.

First, I'll address the accessibility side of the menu. To make the menu available to screen readers, the menu options are placed in standard HTML ordered and unordered lists. Each list element has clickable text that takes you to the appropriate location. I'll omit the actual HREF values (you can view the source and see them for yourself), but here is the HTML used to generate the menu:

<div id="allcategories">
    <ul id="allcategoriesnav">
        <li><a>About Us</a></li>
        <li><a>Web Hosting</a></li>
                <li><a>Web Design</a></li>
                <li><a>Notes Client</a></li>
                <li><a>Formula Language</a></li>
                <li><a>API (Notes/Windows)</a></li>
                <li><a>Regular Expressions</a></li>
        <li><a>Mail Scheduler Application</a></li>
        <li><a>Hint/Tip Mailing List</a></li>
        <li><a>Hint/Tip RSS Feed</a></li>

Since the elements are all listed in standard HTML, screen readers won't have any problem with them. So, how, if you have a standard browser like IE or Firefox, is the menu generated?

Style Sheets are used to do most of the work. Notice how everything was placed inside a <DIV>? That allows complete control through CSS - we can specify rules that only apply to that division, so it won't affect other lists on your web page. Since the "id" was used in the division, all the CSS elements have to start out with the pound sign (#). To work with a specific HTML element in that division (instead of applying it to all HTML elements of the same type) you include the id of the division, then a space, then a name of the HTML element. Here's an example:

#allcategories ul { padding:0px; margin:0px; list-style:none; }

This says that all <UL> tags within the allcategories division have no margin, no padding, and no list style. But that applies only within that division - if you have other lists in other divisions (or not in any division), they won't get this style definition. That allows isolation of this technique only to the menu.

Similarly, if we want to apply a style to a <LI> tag within the list within the division, we can use this style sheet entry:

#allcategories ul li { background:#C0C0C0; border-right:1px solid #FFFFFF; float:left; position:relative; text-align:center; width:12.49%; }

This applies the gray background to all list elements. It gives a small white border so you it doesn't look like one solid line. They are floated next to each other so they all appear on one line. The width makes sure that everything "fits" on the line (without too much white space around it). And each entry is centered in its block.

We have to nest a little further to get to the ordered list entry (the drop down). Initially, this whole drop-down should be hidden, but (when it appears) it needs to appear directly below the "parent" entry. So here's the CSS to achieve that effect:

#allcategories ul li ol { display:none; position:absolute; top:14px; left:0px; width:300px; padding:0px; margin:0px; border-bottom:1px solid #483D8B; list-style:none; background:#FFFFFF; z-index:3; }

Note that positioning is absolute based on the container element. So "left:0px" positions it with the same left-most edge as it's container element, not the left-most edge of the browser window.

For Firefox, we can simply specify that when you hover over a <LI> tag that has a <OL> tag underneath, to now display the stuff that was hidden before. For IE, we have to apply a little JavaScript when the page loads to get it to recognize everything. So we have two CSS entries - the first is for Firefox and the second is for IE:

#allcategories ul li:hover ol { display:block; }
#allcategories ul li.over ol { display:block; }

Finally, we have the CSS applied to each of the list elements in that drop-down. So this is nested even further:

#allcategories ul li ol li { border:1px solid #483D8B; border-bottom:none; clear:left; width:300px; background:#FFFFFF; color:#483D8B; text-align:left; }

The "clear:left" entry means that these elements will appear below each other instead of using the inherited "float:left" entry.

Note that if you look at the CSS for the Breaking Par web site, you'll see a few more entries under the allcategories heading. Those aren't relative to the functionality of the drop-down menu, so they aren't described here.

The description above will work fine in Firefox. But for IE, we need to fix the problem that it won't properly recognize the hover on the <LI> tag. So, on page load, the "startlist" JavaScript function is called. Here's the function:

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

Basically, this code simply applies a class name of "over" to those <LI> tags in the menu when you mouse over them, and removes the class name when you mouse out. So the style sheet definition of "li.over" will take effect, which means the block below (the sub-menu) will be shown. Technically, I guess this is considered DHTML using JavaScript. But if your clients are all Firefox, this JavaScript isn't necessary and the drop-down menu is implemented using only CSS.