1 2 3 4 5 Code Style: Drop down menu using DOM1 and CSS 2 visibility properties 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 48 49 50 51 52 59 60 61 62 63
64 65
66 CSS font stacks, developer FAQs & web standards 67
68
69 79
80
81 82 83 105 112
113 114 115
116 Site navigation below 117
118
119
120

121 134

135

136 Your banner ad here 137

138
139
140

141 In this section 142

143 169

170 Follow Code Style 171

172 183

184 Text ad service 185

186

187 Put your text ad here Down arrow icon 188

189
190 191
192

193 WestNIC provides reliable web hosting services 194

195
196 197
198

199 This article demonstrates a DOM1 drop-down menu system using the CSS visibility property. Each menu has a main link and an unordered list of links that become visible, with the illusion of extending the main menu point downwards. The drop down menus are open source, accessible and forward compatible. 200

201

202 The scripts and CSS for these drop down menus is provided under a Creative Commons License. 203

204

205 Browser-safe and forward-compatible 206

207

208 Developing DHTML 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. 209

210

211 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. 212

213

214 Accessibility features 215

216

217 These menus also implement tab navigation in supporting browsers by placing tabindex attributes on each link. These are combined with Javascript onfocus and onblur event handlers that control the menus in the same way as the onmouseover and onmouseout events respectively. If you press the tab key on your keyboard, the first menu heading should be selected and the menu list will open. Subsequent tabs will select each item in the menu list, then select and open the second menu and continue to the last. Press enter to open a selected link. Press shift+tab to move backwards through the items. 218

219

220 Error checking 221

222

223 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. 224

225

226 Compatibility check 227

228

229 This page has been tested and successfully debugged in the following browsers. The scripts are compatible and fully supported by the DOM1 enabled browsers in the Supported column. 230

231 232 235 236 237 240 243 246 247 248 249 252 255 258 259 260 263 266 269 270 271 274 277 280 281 282 285 288 291 292 293 296 299 302 303 304 307 310 313 314
233 Script compatibility in specific browser versions 234
238 Browser 239 241 Compatible 242 244 Supported 245
250 Internet Explorer 251 253 3.0, 4.0 254 256 5.0, 5.5 and all versions since 257
261 Firefox 262 264   265 267 0.8, 0.9.1 and all versions since 268
272 Mozilla 273 275   276 278 M15, 0.9.3, 1.3.1 279
283 Netscape Navigator 284 286 3.04, 4.5, 4.73 287 289 6.0, 7.1 290
294 Opera 295 297 3.62 298 300 4.0, 5.0 and all versions since 301
305 Safari 306 308   309 311 85, 94 and all versions since 312
315

316 Netscape version 7.1 is based on Mozilla version 1.4. Firefox is also based on the Mozilla browser. 317

318

Known incompatibilities

319

320 It has been reported that the standard Code Style stylesheets crash Netscape Navigator 4 on Windows XP and Windows 2000 when viewed with this page. 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 85 and 94 are reported to render the menus successfully. 321

322

323 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. 324

325

326 Drop down menu source code 327

328

329 The scripting, CSS and XHTML markup for this drop down menu system is described below and the source code is heavily commented for reference. The scripts and CSS for these drop down menus is provided under a Creative Commons License. 330

331

332 For easy maintenance and modular design, all the Javascript (and CSS) for this page is referenced from external files. Unsupported 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: 333

334 354

355 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. 356

357

358 HTML code for drop down menu 359

360 361 362

363 visibility-HorizontalMenus.shtml 364

365

366 The markup fragment below specifies the supplementary stylesheet for this page and the initial script element that loads the menu builder script: 367

368
369  <link rel="stylesheet" type="text/css"
370   href="/styles/javascript/dom/visibility-HorizontalMenus.css" />
371  <script type="text/javascript"
372   src="/scripts/dom/css/visibility-HorizontalMenuBuilder.js">
373  </script>
374        
375

376 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: 377

378
379  <script type="text/javascript"
380    src="/scripts/dom/css/visibility-HorizontalMenuWriter.js">
381  </script>
382  <noscript>
383    <div id="NavBar">
384      <!-- LinkBar points should match LinkBar points in
385           /scripts/dom/css/visibility-HorizontalMenuBuilder.js -->
386      <div id="LinkBar">
387        <div id="Link1"><a href="/">Home page</a></div>
388        <div id="Link2"><a href="#">Javascript</a></div>
389        <div id="Link3"><a href="#">DOM</a></div>
390        <div id="Link4"><a href="#">CSS</a></div>
391        <div id="Link5"><a href="#">What's New</a></div>
392      </div>
393    </div>
394  </noscript>
395        
396

397 Javascript code for drop down menu 398

399

400 visibility-HorizontalMenuBuilder.js 401

402

403 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. 404

405
406  if (document.getElementById){
407    // DOM1 statements
408  }
409        
410

411 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. 412

413

414 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. 415

416

417 menuOver() 418

419

420 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. 421

422

423 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. 424

425
426  // This is the new 'live' menu, make it visible
427  LiveMenu = document.getElementById(MenuID);
428  // LiveMenu.style.visibility is
429  // initially empty in IE5 until
430  // it is assigned by these
431  // functions, so must check that
432  // it's not null before proceeding...
433  if ((LiveMenu.style) && (LiveMenu.style.visibility != null)){
434    LiveMenu.style.visibility = 'visible';
435  }
436        
437

438 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. 439

440

441 stayOpen() 442

443

444 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. 445

446
447  function stayOpen(MenuID){
448    // If menuOver has not been called
449    // or the menu is hidden, do nothing
450    if ((LiveMenu == null)||
451        ((LiveMenu.style) &&
452         (LiveMenu.style.visibility) &&
453         (LiveMenu.style.visibility == 'hidden'))) return;
454    else menuOver(MenuID);
455  }
456        
457

458 menuOut() 459

460

461 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. 462

463

464 hideNow() 465

466

467 As its name implies, this function immediately "closes", or makes hidden, whichever menu is specified by the global LiveMenu variable: 468

469
470  if ((LiveMenu.style) && (LiveMenu.style.visibility)) {
471    LiveMenu.style.visibility = 'hidden';
472  }
473        
474

475 visibility-HorizontalMenuWriter.js 476

477

478 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: 479

480
481  // If menutxt is defined and not
482  // empty, write it to the document
483  ///////////////////////////////////////
484  if ((menutxt) && (menutxt != '')) {
485    document.write(menutxt);
486  }
487        
488

489 Here again, the core Javascript method document.write() is assumed to be available if this external script file has loaded. 490

491

492 CSS visibility code for drop down menus 493

494

495 visibility-HorizontalMenus.css 496

497

498 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. 499

500
501  /*
502    Created:  2000-10-21
503    Issued:   2001-01-11
504    Modified: 2005-02-23
505  
506    Copyright (c) 2001-2006 by Philip Shaw, phil@codestyle.org
507  
508    This work is licensed under the Creative Commons
509    Attribution-NonCommercial-ShareAlike License.
510    To view a copy of this license, visit
511    http://creativecommons.org/licenses/by-nc-sa/2.0/
512    or send a letter to Creative Commons, 559 Nathan
513    Abbott Way, Stanford, California 94305, USA.
514  */
515  
516  @import url(visibility-HorizontalMenusImport.css);
517  /*
518    Basic styles for NN4.
519  */
520  #Link1, #Link2, #Link3, #Link4, #Link5 {
521    float:            left;
522    width:            17.9%;
523  }
524  #Header{
525    clear:            left;
526  }
527        
528

529 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. 530

531

532 visibility-HorizontalMenusImport.css 533

534

535 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 divs. 536

537
538  /*
539    Created:   2000-11-12
540    Issued     2001-01-11
541    Modified:  2010-04-05
542  
543    Copyright (c) 2001-2009 by Philip Shaw, phil@codestyle.org
544  
545    This work is licensed under the Creative Commons
546    Attribution-NonCommercial-ShareAlike License.
547    To view a copy of this license, visit
548    http://creativecommons.org/licenses/by-nc-sa/2.0/
549    or send a letter to Creative Commons, 559 Nathan
550    Abbott Way, Stanford, California 94305, USA.
551  */
552  /*
553    Increase depth of top bar for menus
554  */  
555  #TopBar {
556    padding-top: 2.5em;
557  }
558  #MenuBar, #LinkBar {
559    float:            none;
560    width:            95.9%;
561    position:         absolute;
562    left:             2.7%;
563    border:           none;
564  }
565  /*
566    z-index necessary to make links
567    visible in Netscape 6
568  */
569  #MenuBar {
570    top:              1.5em;
571    z-index:          4;
572  }
573  #LinkBar {
574    top:              0.1em;
575    z-index:          3;
576  }
577  /*
578    Main menu and link styles identical.
579  */
580  #Menu1, #Menu2, #Menu3, #Menu4, #Menu5,
581  #Link1, #Link2, #Link3, #Link4, #Link5 {
582    float:            left;
583    width:            17.9%;
584    border-style:     solid;
585    border-color:     #fefefe #dfdfdf #666 #ccc;
586    margin:           0.6% 0.2%;
587    padding-left:     1%;
588    color:            #039;
589    background:       #f9f9f9;
590    font-family:      "Bitstream Charter", "URW Palladio L", Palatino, "Palatino Linotype", "Hoefler Text", Georgia, "Book Antiqua", Times, "Times New Roman", serif;
591    font-weight:      normal;
592    font-size:        1.1em;
593  }
594  /*
595    Differences in menu and link styles.
596  */
597  #Menu1, #Menu2, #Menu3, #Menu4, #Menu5 {
598    border-width:     0px 2px 1px 2px;
599    visibility:       hidden;
600  }
601  #Link1, #Link2, #Link3, #Link4, #Link5 {
602    border-width:     2px 2px 1px 2px;
603    visibility:       visible;
604    height:           1.3em;
605  }
606  /*
607    Must override float on the menu divs.
608  */
609  #Menu1 ul, #Menu2 ul, #Menu3 ul,
610  #Menu4 ul, #Menu5 ul  {
611    float:            none;
612    margin:           0em 0em 0em 1em;
613    padding:          0.2em 0em 0.5em 0em;
614    font-family:      "Bitstream Charter", "URW Palladio L", Palatino, "Palatino Linotype", "Hoefler Text", Georgia, "Book Antiqua", Times, "Times New Roman", serif;
615  }
616  /*
617    Make the whole width of the links
618    active -- height necessary for IE 5.5
619  */
620  #LinkBar a, #MenuBar a {
621    display:          block;
622    height:           1.3em;
623  }
624  #Menu1 a:visited, #Menu2 a:visited,
625  #Menu3 a:visited, #Menu4 a:visited,
626  #Menu5 a:visited, #Link1 a:visited,
627  #Link2 a:visited, #Link3 a:visited,
628  #Link4 a:visited, #Link5 a:visited {
629    color:            #039;
630    background:       #f9f9f9;
631  }
632  #Menu1 a:link, #Menu2 a:link,
633  #Menu3 a:link, #Menu4 a:link,
634  #Menu5 a:link, #Link1 a:link,
635  #Link2 a:link, #Link3 a:link,
636  #Link4 a:link, #Link5 a:link {
637    color:            #039;
638    background:       #f9f9f9;
639  }
640  #Menu1 a:hover, #Menu2 a:hover,
641  #Menu3 a:hover, #Menu4 a:hover,
642  #Menu5 a:hover, #Link1 a:hover,
643  #Link2 a:hover, #Link3 a:hover,
644  #Link4 a:hover, #Link5 a:hover {
645    color:            #C00;
646    background:       #f9f9f9;
647  }
648        
649

650 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. 651

652

653 The final declarations for .Title and #Header simply move these standard page components down further than normal to accommodate the height of the menus. 654

655

656 Style note 657

658

659 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. 660

661

662 Drop down menu FAQ 663

664 719

720 Related articles 721

722 730
731
732 733 734
735

736 Article feedback 737

738

739 Your comments on this article will be appreciated, please use the form below to submit your views. If you would like a reply or article update notification, include your email address. 740

741
742 743 744 745 746 747 752 755 756 757 762 766 767 768 773 796 797 798 803 806 807 808 813 814 815 818 819 820 825 838 839 840 843 846 847 848 849
850

851 Information: Your email address will not be mis-used. If you include your address you may be sent a personal reply, you will not be added to any mailing list unless you request update notification. Read the site privacy statement for details. 852

853
854
855 899
900 908 Add this page to your chosen social bookmarking service 909 910
911
912 925 938
939

940 Style warning, please read 941

942
943 Home · 944 CSS · 945 Java · 946 Javascript · 947 HTML · 948 Help · 949 Log 950
955 956 957