visibility
menus
This article illustrates a set of DOM1 drop-down menus using the CSS visibility
property, which have a main link and several sub-classified links. The
sub-menus demonstrated on this page don't drop down at all, they just
become visible, giving the illusion of extending the main link tile
downwards.
The scripting, CSS and XHTML markup for this menu system is described below and the source code is heavily commented for reference. Few of the hyperlinks on the menus point to valid URLs, most are just null fragment anchors, #
. Convenient links are provided to download the source code further down this page.
Developing so-called "dynamic HTML" that is fully backward- forward- and cross-compatible with all browsers has been a fundamental problem since client-side scripting was implemented in more than one Web browser. The DOM1 recommendation from the W3C defines a standard hierarchy of reference objects for HTML 4.01 and XHTML 1.0 documents that should at least make browser-safe forward-compatible scripting feasible.
This demonstration page is assumed to be safe in all browsing circumstances; it will not cause Javascript errors, but is only intended to be fully supported by DOM1 enabled browsers. The scripting is not intended to work with the mutually incompatible, proprietary DOMs implemented by Netscape 4 and Internet Explorer 4 or earlier browsers; in these cases the browser just displays the main menu points statically. On the other hand, the code is guaranteed to be forward-compatible because it uses method, object and property checking to ensure that only DOM1 enabled browsers execute the relevant code.
The main menu builder script includes a couple of workarounds to
address slight inconsistencies in the way that Opera 4.0 and Internet
Explorer 5.0 handle the CSS z-index
property and the DOM1 .style.visibility
property respectively. Both workarounds use browser-neutral condition
checking to be meticulously fail-safe and don't affect the script's DOM1 compatibility.
This page has been tested and successfully debugged in the following browsers and is fully supported by the DOM1 enabled browsers in this style, marked *:
Browser | Compatible | Supported |
---|---|---|
Internet Explorer | 3.0, 4.0 | 5.0, 5.5 |
Mozilla | M15, 0.9.3, 1.3.1 | |
Netscape Navigator | 3.04, 4.5, 4.73 | 6.0, 7.1 |
Opera | 3.62 | 4.0, 5.0, 5.11, 6.0b, 6.01, 7.11 |
Safari | 8.5 |
Netscape version 7.1 is based on Mozilla version 1.4.
It has been reported that the standard Code Style stylesheets crash Netscape Navigator 4 on Windows XP and Windows 2000. These style sheets have since been hidden from Netscape 4. It has also been reported that the Mac Safari browser does not render this menu system accurately; the menus appear twice, slightly offset (Safari screen shot, 60KB). However, Safari version 8.5 is reported to render the menus successfully.
If you encounter a problem with this page using a browser not listed here, please use the article feedback form below to submit a report.
For easy maintenance and modular design, all the Javascript (and CSS)
for this page is referenced from external files. Non-supporting
browsers such as Internet Explorer 3 and Netscape 2 with Javascript on will not display these menus at all, nor any noscript
element, so this menu system should not be used for essential navigation links. The external script and CSS files are as follows, see below for details:
See the Code Style help and FAQ page for information on debugging external CSS and Javascript files.
As with all Javascript for the Web, one cannot be sure that the end-users' browser has Javascript support, so there is a noscript
block with links for each of the main menu points using similar markup
to the dynamic menus so that the styles may still be presented
accurately even if Javascript is off.
visibility-HorizontalMenus.shtml
The markup fragment below specifies the supplementary stylesheet for this page and the initial script
element that loads the menu builder script:
<link rel="stylesheet" type="text/css" href="/styles/javascript/dom/visibility-HorizontalMenus.css" /> <script type="text/javascript" src="/scripts/dom/css/visibility-HorizontalMenuBuilder.js"> </script>
The fragment below shows the script
element that loads the menu writer script and inserts the dynamic menus immediately after the open body
tag. There is also a simplified noscript
alternative with equivalent id
attributes:
<script type="text/javascript" src="/scripts/dom/css/visibility-HorizontalMenuWriter.js"> </script> <noscript> <div id="NavBar"> <!-- LinkBar points should match LinkBar points in /scripts/dom/css/visibility-HorizontalMenuBuilder.js --> <div id="LinkBar"> <div id="Link1"><a href="/">Home page</a></div> <div id="Link2"><a href="#">Javascript</a></div> <div id="Link3"><a href="#">DOM</a></div> <div id="Link4"><a href="#">CSS</a></div> <div id="Link5"><a href="#">What's New</a></div> </div> </div> </noscript>
visibility-HorizontalMenuBuilder.js
This menu builder script defines the drop-down menu contents and event handler functions for the menus. If the DOM1 getElementById()
method is supported, the string variable menutxt
is used to build the menu headings and bullet lists. If this basic DOM1 feature is not supported, a simplified group of menu headings is compiled equivalent to the noscript
markup.
if(document.getElementById){ // DOM1 statements }
This script also checks if DOM1 object references and properties are available before use, in particular the elements' .style
object and .style.visibility
property, see the menuOver()
example below.
All core Javascript features are assumed to be available if this external script file is loaded and are not explicitly checked. The script is not listed here because of long lines but is heavily commented for reference, see visibility-HorizontalMenuBuilder.js.
menuOver()
The menuOver()
function is called directly when the cursor triggers the onmouseover
event on one of the five menu headings. This function checks if any
other menus are "open" and, if so, closes them immediately. It then
opens, or makes visible
, the relevant menu by reference to its visibility
property via the global variable LiveMenu
.
This function includes a minor workaround to check that the LiveMenu.style.visibility
property is not null
,
as this value initially appears to be the empty string in Internet
Explorer 5.0 (in IE4.0 compatibility mode at least) and does not return
true
.
// This is the new 'live' menu, make it visible LiveMenu = document.getElementById(MenuID); // LiveMenu.style.visibility is // initially empty in IE5 until // it is assigned by these // functions, so must check that // it's not null before proceeding... if((LiveMenu.style)&&(LiveMenu.style.visibility!=null)){ LiveMenu.style.visibility = 'visible'; }
After this statement sets the visibility
property, IE5 returns true
to the simpler conditions in the other event handler functions, which simply check for the existence of the .style.visibility
property.
stayOpen()
Even when the extended menus' visibility
property is hidden
, Opera 4.0 registers onmouseover
events on the drop-down bullet lists because it does not support the CSS z-index
property. The stayOpen()
function is a workaround to suppress this behaviour, which simply
checks to see if the menu is logically "open" and forwards a call to menuOver()
if it is. If the menu is supposed to be closed, the function returns immediately.
function stayOpen(MenuID){ // If menuOver has not been called // or the menu is hidden, do nothing if((LiveMenu==null)|| ((LiveMenu.style)&& (LiveMenu.style.visibility)&& (LiveMenu.style.visibility=='hidden')))return; else menuOver(MenuID); }
menuOut()
The menuOut()
function is triggered by onmouseout
events in the exposed bullet list anchors. The function initialises a setTimeout()
control that holds a given menu open for 250 milliseconds so the user can move the cursor down the list before it closes. If stayOpen()
calls are triggered by the onmouseover
event handlers in these lists, the menus stay open. If not, the hideNow()
function is called when the timeout expires.
hideNow()
As its name implies, this function immediately "closes", or makes hidden
, whichever menu is specified by the global LiveMenu
variable:
if((LiveMenu.style)&&(LiveMenu.style.visibility)){ LiveMenu.style.visibility = 'hidden'; }
visibility-HorizontalMenuWriter.js
This menu writer script simply writes the XHTML markup for the menus defined in the menu builder script into the flow of the document. If the global string variable menutxt
has not been defined for whatever reason, the menus will not be output. The listing for visibility-HorizontalMenuWriter.js is given below:
// If menutxt is defined and not // empty, write it to the document /////////////////////////////////////// if((menutxt)&&(menutxt!='')){ document.write(menutxt); }
Here again, the core Javascript method document.write()
is assumed to be available if this external script file has loaded.
visibility-HorizontalMenus.css
This stylesheet, visibility-HorizontalMenus.css, supplements the standard site-wide Code Style CSS to declare styles specifically for these drop-down menus. It uses an @import
rule to hide the main styles from Netscape 4 and Internet Explorer 3,
but some simple styles are included to improve appearances where
supported.
/* --------------------------------- */ /* visibility-HorizontalMenus.css */ /* --------------------------------- */ /* Created 2000-10-21 */ /* Issued 2001-01-11 */ /* Modified 2002-01-05 */ /* Checked 2002-01-05 */ /* Copyright (c) 2001-2004 by */ /* Philip Shaw, all rights reserved. */ /* --------------------------------- */ @import url(visibility-HorizontalMenusImport.css); /* Basic styles for NN4. */ #Link1, #Link2, #Link3, #Link4, #Link5{ float: left; width: 17.9%; } #Header{ clear: left; }
The series of grouped #Link1
declarations refer to the main link heading div
elements, which float horizontally across the top of the page. These
are sized using percentage lengths to ensure that these menu panels
will scale proportionally to fit most screen resolutions. These are
styled in more detail by margin
, padding
and border
declarations in the @import
stylesheet.
visibility-HorizontalMenusImport.css
The @import
stylesheet, visibility-HorizontalMenusImport.css,
declares the detailed presentation of the menus for supporting
browsers. Non-supporting browsers will display a simpler page format.
In many cases the declarations have been grouped to ensure that display
properties and positioning of the menu and bullet list containers, #LinkBar
and #MenuBar
, are almost identical. The vital exceptions are the z-index
and vertical positioning given by the top
property, which makes them overlap very slightly on the bottom edge of the menu heading div
s.
/* --------------------------------- */ /* Created 2000-11-12 */ /* Issued 2001-01-11 */ /* Modified 2002-01-05 */ /* Checked 2002-01-05 */ /* Copyright (c) 2001-2004 by */ /* Philip Shaw, all rights reserved. */ /* --------------------------------- */ /* Move the Code Style logo down beneath the menus: background-position: [horiz.] [vert.] */ BODY{ background: url(/images/CodeStyleFeint.gif) no-repeat -68px -60px #FFF; color: #000; } #MenuBar, #LinkBar{ float: none; width: 99%; position: absolute; left: 0.8%; border: none; } /* z-index necessary to make links visible in Netscape 6 */ #MenuBar{ top: 1.5em; z-index: 4; } #LinkBar{ top: 0.1em; z-index: 3; } /* Main menu and link styles identical. */ #Menu1, #Menu2, #Menu3, #Menu4, #Menu5, #Link1, #Link2, #Link3, #Link4, #Link5{ float: left; width: 17.9%; border-style: solid; border-color: #eee #dfdfdf #666 #ccc; margin: 0.6% 0.3%; padding-left: 1%; color: #039; background: #eee; font-family: "times new roman", serif; font-weight: normal; font-size: larger; text-transform: lowercase; } /* Differences in menu and link styles. */ #Menu1, #Menu2, #Menu3, #Menu4, #Menu5{ border-width: 0px 2px 1px 2px; visibility: hidden; } #Link1, #Link2, #Link3, #Link4, #Link5{ border-width: 2px 2px 1px 2px; visibility: visible; height: 1.3em; } /* Must override float on the menu divs. */ #Menu1 UL, #Menu2 UL, #Menu3 UL, #Menu4 UL, #Menu5 UL{ float: none; margin: 0em 0em 0em 1em; padding: 0.2em 0em 0.5em 0em; font-family: "times new roman", serif; } #Menu1 A:visited, #Menu2 A:visited, #Menu3 A:visited, #Menu4 A:visited, #Menu5 A:visited, #Link1 A:visited, #Link2 A:visited, #Link3 A:visited, #Link4 A:visited, #Link5 A:visited{ color: #039; background: #EEE; } #Menu1 A:link, #Menu2 A:link, #Menu3 A:link, #Menu4 A:link, #Menu5 A:link, #Link1 A:link, #Link2 A:link, #Link3 A:link, #Link4 A:link, #Link5 A:link{ color: #039; background: #EEE; } #Menu1 A:hover, #Menu2 A:hover, #Menu3 A:hover, #Menu4 A:hover, #Menu5 A:hover, #Link1 A:hover, #Link2 A:hover, #Link3 A:hover, #Link4 A:hover, #Link5 A:hover{ color: #C00; background: #EEE; } /* Substitute padding for omitted Code Style URI. */ .Title{ padding-top: 1em; } /* Push #Header down to make room for menus, margin-top doesn't have the same effect with IE5.5 and Mozilla, so the logo image must be moved set to 100% (bottom) too. */ #Header{ padding-top: 4%; background: url(/images/CodeStyle.gif) transparent no-repeat 96% 100%; color: #000; }
The numbered series of ten paired #Link1
and #Menu1
declarations for the five menus are handled in a similar way by grouped
selectors. The vital differences between these selectors, visibility
, border-top
and height
are declared beneath and complete the illusion of the extensible drop-down panel.
The final declarations for .Title
and #Header
simply move these standard page components down further than normal to accommodate the height of the menus.
The specificity of the A:hover
property in the drop-down menus is evidently being calculated
differently in Netscape 6, compared with Opera 5 and Internet Explorer
5. Netscape 6.0 and 6.1 do not show the hover style, but this bug is
fixed in Mozilla build 2001092003 and later.
For general debugging guidance, see the main Help & FAQ section, for specific questions about working with the DOM1 visibility menu see the dynamic menus questions below.
table
layout?
@import
styles override the primary stylesheet?
[ Home ] [ CSS ] [ Java ] [ Javascript ] [ Site log ] [ Anchor Points ] [ Help ]