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

Pushing the Envelope

Do you know about www.Macromedia.com? How do you like the menu system there? What about the links that pop up horizontally under the main navigation menu? I think it's different than the dropdown menus that "pop up " all over the place nowadays.

Check it out!

Enhancements made to the previous version:

  1. All List Items spread horizontally,
  2. For better accessibility, I've dropped visibility and went for a negative left value (as in the Suckerfish article),
  3. 2 JS events have been added so it is possible now to tab through the entire menu with MSIE,
  4. A short script is used to dynamically assign all event handlers,
  5. An extra style sheet (highlighted code below) and a very short script, both MSIE "specific", have been added to prevent the menu system to fall apart in case "Active Scripting" is disabled.
  6. The empty string used to swap classes has been replaced with the actual class value of the Top Level lis (this seems to correct - more or less - a small Safari issue).

Take noteI've tried different solutions to hide the sub level uls but left seems to be what works best (MSIE doesn't play ball with z-index and I had trouble using text-indent with NN6).

Take noteIf you're using only 1 or 2 Top Level Links to trigger sub links, you may think that #3 is not necessary better than assigning the events directly through the markup; and you may be right in term of "footprint". But it is a good habit to separate behavior from structure.

This is the content of our 2 CSS files:

This first file shows the negative left value technique that replaces visibility:hidden

/* all lists */
#TJKDropDownMenu a,
#TJKDropDownMenu a:link,
#TJKDropDownMenu a:visited {
font-size:.9em;
color:navy
}
#TJKDropDownMenu,
#TJKDropDownMenu ul {
padding:0;
margin:0 0 0 6px;
width:750px
}
/* Nested ULs */
#TJKDropDownMenu li ul {
position:absolute;
top:1.8em;
left:-900px
}
/* All LIs */
#TJKDropDownMenu li {
float:left;
width:auto;
margin:0;
padding:0;
list-style-type:none;
font-weight:600;
border-bottom:1px solid #004284
}
#TJKDropDownMenu li a {
padding:.1em .4em;
height:2em;
line-height:2em;
border-bottom:2px solid #e6ecf3;
background:url(/articles/dropdown/img/pipe.gif) right center no-repeat transparent
}
#TJKDropDownMenu li a:hover {
background-color:#004284;
background-image:none;
color:#fff;
border-bottom:2px solid #004284
}
#TJKDropDownMenu li ul li a {
line-height:1.7em;
height:1.7em;
font-weight:400;
border:none;
color:#333;
background-image:none
}
/* we reset the margin for the children */
#TJKDropDownMenu li ul li {
margin:0;
border-bottom:0;
border-right:1px solid #004284
}
#TJKDropDownMenu li:hover ul,
#TJKDropDownMenu li.msieFix ul {left:9px}

The purpose of this second style sheet is to make sure our menu is well formatted when viewed in MSIE when Active Scripting is disabled. So to hide the following rules from "decent" browsers and to call the sheet only when "Active Scripting" is disabled, we do 2 things:

  1. We use the star html selector to target MSIE only.
  2. We use a short JavaScript statement to disable that sheet.
* html #TJKDropDownMenu li ul {
margin:0;
position:relative;
left:9px;
top:0
}
* html #TJKDropDownMenu li {border-bottom:0}
* html #TJKDropDownMenu li.trigger {width:250px}
* html #TJKDropDownMenu {background-color:#e6ecf3}

Additions to the Markup:

Before the </head> tag of the document:

<style type="text/css" media="screen">
<!--
@import url(/css/basic.css);
-->
</style>
<link rel="stylesheet" href="/css/msie.css" type="text/css" />
<script type="text/javascript" src="/js/turnoffmsiecss.js"></script>
<script type="text/javascript" src="/js/js4msie.js"></script>
<!--[if IE 5]>
<style type="text/css" media="screen">
* html #TJKDropDownMenu li ul {top:2.2em}
* html #TJKDropDownMenu li ul li a {line-height:1.4em;height:1.4em}
</style>
<![endif]-->

Content of the 1st external JavaScript file (turnoffmsiecss.js):

<!--
if(document.styleSheets) document.styleSheets[1].disabled=true
//-->

Take noteNote that no matter how many "@import" statements we have inside the style tags pair, only the first one feeds the array. For example, if we had 3 sheets in the same style container, the value inside the brackets would still be 1.

This is the 2nd external JavaScript file (js4msie.js), this one writes the event handlers for us. This script also makes tabbing navigation possible through the menu:

<!--
// Copyright (c) TJKDesign - Thierry Koblentz
// Setting all the Event Handlers Dinamically
function swap(){this.className="msieFix"}
function swapBack(){this.className="trigger"}
function swapfocus() {this.parentNode.parentNode.parentNode.className="msieFix"}
function swapblur() {this.parentNode.parentNode.parentNode.className="trigger"}
function TJKSetEvents(){
if (document.getElementById){
var LI = document.getElementsByTagName("li");
var zLI= LI.length;
for(var k=0;k<zLI;k++){
if(LI[k].parentNode.parentNode.className=="trigger"){LI[k].firstChild.onfocus=swapfocus;LI[k].firstChild.onblur=swapblur}
if(LI[k].className=="trigger"){LI[k].onmouseover=swap;LI[k].onmouseout=swapBack}
}
}
}
//-->

We use the onload attribute of the <body> tag to call TJKSetEvents():

<body onload="TJKSetEvents()">

We plug below the body tag a MSIE CC inside a noscript tags pair to take care of the IE5 broken box model in case the second sheet is used (if "Active Scripting" is disabled):

<noscript>
<!--[if IE 5]>
<style type="text/css" media="screen">
* html #TJKDropDownMenu li ul {top:0}
* html #TJKDDM #current ul {top:0}
* html #TJKDropDownMenu ul a:hover {line-height:17px}
</style>
<![endif]-->
</noscript>

Replacing the onmouseover/onmouseout events with a class attribute in the Top Level lis used to trigger Sub Links:

<li class="trigger"><a href="javascript:;">About Us</a>

Check it out!

Et VoilĂ !