Firefox: Problem with DHTML Menus

Note: This problem was rectified in Firefox version 1.5 for both Mac OS X and Windows.

The problem defined

The two menus below are identical in every way, except the manner in which the sub-menu flyouts are activated (see below for details.) Both have two levels of sub-menus.

Both menus work perfectly in Safari (v1.3 & 2.0).

the problem with Firefox

DHTML menu in Firefox 1.0 showing that submenu items are not hidden when the mouse is moved out

The CSS menu works perfectly in Firefox (v1.0 for both Windows and Mac) and Camino (v0.8.1), but not in Internet Explorer (v5.5 or 6.0 for Windows, or v5.2.3 for Mac) because Internet Explorer doesn't support the :hover pseudoclass for any element other than the A element.

The DHTML menu works perfectly in Internet Explorer (all versions), but there's a problem with Firefox (both platforms) and Camino.

If you mouse-over the menu items in Firefox/Camino, the sub-menus fly out as expected. But they aren't always hidden again during mouse-out, leaving them 'stuck' open.

A solution, of sorts

In order to get the menus to work effectively across browsers, it's necessary to have both a CSS-based menu (for Firefox/Camino) and a DHTML-based menu (for Internet Explorer.) But this is hardly ideal, requiring additional unnecessary code and a browser sniffer to ensure that only Internet Explorer gets served the DHTML.

Some might say that it would be easier if Internet Explorer supported the :hover pseudoclass for elements other than just the A element, and they would have a valid point, at least to an extent. After all, if the visitor has disabled JavaScript support in the browser, then the DHTML menu will not work. The CSS menu will always work as intended in modern, standards-compliant browsers.

Although this is true, if the visitor has indeed disabled JavaScript a lot of other things on other sites won't work either. This may be a blessing or a curse, depending on the sites that the visitor frequents!

But should Internet Explorer support :hover for other elements, so that we can rely on CSS-based menus?

If one accepts the semantics-driven approach to web design as evangelised by W3C and others, then the :hover pseudoclass is incorrect, because it combines presentation (CSS) with behaviour. Behaviour should be separated from presentation by scripting the DOM.

As such, the DOM-based scripting approach to enable the menus in Internet Explorer is ‘correct’. The fact that Firefox doesn't work well with this approach, is a poor reflection on that browser.

Summary table: browser support for the two menus
Operating system Browser version CSS menu DHTML menu
OS X Safari 1.3 full full
Firefox 1.0.4 full flawed
1.5.0.4 full full
Netscape 6.2.3 none flawed
7.1 full flawed
Camino 0.8.1 full flawed
1.0.1 full full
Internet Explorer 5.2.3 none full
Opera 8.0.1 full full
iCab 3.0.2 (beta) full full
Windows Internet Explorer 5.5 none full
6.0 none full
Firefox 1.0.4 full flawed
1.5.0.4 full full
Opera 8.0 full full

How the menus work

The menus are identical in every way with respect to the underlying HTML and CSS, with the following exceptions.

The CSS menu uses the :hover pseudoclass as follows:

#menu1 li:hover>ul { display: block; }

The DHTML menu, on the other hand, uses a W3C DOM script:

window.onload = function () { var li = document.getElementsByTagName('LI'), i; for (i = 0; i < li.length; i++) { var obp = li[i].parentNode; if (obp.id == 'menu2' || obp.parentNode.parentNode.id == 'menu2') { li[i].onmouseover = function() { MenuRollover(this,'over'); } li[i].onmouseout = function() { MenuRollover(this,'out'); } } } } function MenuRollover(ob,state) { var vis; switch (state) { case 'over': vis = 'block'; break; case 'out': vis = 'none'; break; default: break; } for (var i = 0; i < ob.childNodes.length; i++) { if (ob.childNodes[i].nodeName == 'UL') ob.childNodes[i].style.display = vis; } }

Endnote

Since I wrote this article, it appears (2006) that IE7 will support the :hover pseudoclass for other elements. The problem with Firefox and Camino was rectified in versions 1.5 and 1.0 respectively.