Documents
Resources
Learning Center
Upload
Plans & pricing Sign in
Sign Out

Drop Down Menus tutorial

VIEWS: 59 PAGES: 15

drop down menus tutorial

More Info
									                                                                                      Drop Down Menus With Standards
                                                                                                         Matt Machell




Drop Down Menus With Standards
Drop Down Menus have been part of the DHTML dictionary for a long time. They're a popular way to cram
lots of navigation elements into a small amount of space. They work in a similar way to the menus that
everybody is used to using in other programs, so offer a familiar environment.

The trouble is that many of the DHTML menus you'll find out there are from the bad old days of the browser
wars, they use huge amounts of code to check for compatibilities, and fail to take into account accessibility
or web standards.

In this article we'll look at some of the ways you can build a drop down menu using CSS and W3C DOM
(Document Object Model)-based JavaScript. We'll also look at some options for improving the menu's
accessibility. We'll use some navigation for a toyshop in our example, but changing it to suit your needs is
very straightforward.

Whilst you can just cut and paste the code, I'd recommend a basic knowledge of JavaScript and CSS
before following the tutorial.



How We Used to do It
In the old days menus of this kind were created entirely using JavaScript. A set of variables was tweaked to
create the items on the menu, and the script built the menu when the page loaded.

The fact that the scripts often involved heavy browser detection (so that they could appease the quirks of
each browser), made for very big, unwieldy, pieces of code. Developers then often optimised for download
by going with very short variable names, thus making them nigh on unreadable if a bug appeared (as they
often did when a new browser was released).

The fact that the menus required JavaScript to work meant that users without it (such as screenreaders or
search engine spiders) couldn't actually find the navigation. Neither could anybody who didn't access the
web using a mouse, since keyboard based navigation was non-existent.

All in all they were a mess of bad practices.

Web Standards to the Rescue?
Web standards offer us a more elegant solution. Since all browsers that support web standards should work
the same way, our browser detection suddenly becomes a non-issue.

Similarly, by making sure our navigation is made up of semantically valid tags, we can ensure that anybody
without JavaScript still gets the links. Since they're tags, they can be navigated by keyboard rather than
mouse, and simply altering the CSS with JavaScript can make it readable to all.



How it Works
Our menu is built up of a list of link items (as you may have guessed if you read my previous article on CSS
Tabs for Beginners) styled with CSS. The default styling (from a class called .default) is a basic look that
anybody without JavaScript enabled will see.

When the page loads in a modern browser, a JavaScript will convert the list items into a drop down menu by
altering which styles are applied (using a class called .vert) and setting onmouseover and onmouseout
events on our menu items, allowing for the dropdowns to appear.
                                   Copyright © 2004 DMXzone.com All Rights Reserved
                                           To get more go to DMXzone.com
                                                   Page 1 of 15
                                                                                      Drop Down Menus With Standards
                                                                                                         Matt Machell




Finally, if the user has JS enabled, but can't access the menu with a mouse, they can switch the menu style
back to the default by clicking a link. We'll code in some use of cookies, so that the browser remembers
which style of menu the user likes, so they don't have to continually change it themselves.

First Things First, Solid Markup
In Dreamweaver, create a new XHTML page using File > New > Basic Page > HTML and make sure the Make
XHTML compliant box is ticked. Save this file as menu.htm.

Go to code view and add the following markup:

<ul class="default" id="menu">
  <li><a href="#">Blocks</a></li><li class="parent"><a href="#">Balls</a><ul><li><a
href="#">Red</a></li><li><a href="#">Yellow</a></li><li><a
href="#">Green</a></li></ul></li><li><a href="#">Bears</a></li><li><a href="#">Menu
Style</a></li>
</ul>
  <div id="content">Some Content</div>

This markup gives us a basic list, which will become our navigation and a div that will hold our content.
We've run all the <li> tags together to avoid some rendering problems that occur in some browsers.

Notice that the last menu item (Menu Style) is actually the link that will alter the menu from one style to
another.

Also this code contains several classes and id's that we'll make use of later. The list item that contains our sub-
list has a class of parent, and the main list has an id of menu and a class of default.

If you switch to design view, you will see the basic layout below:




Not very exciting, but it shows our structure. We have four main categories (Blocks, Balls, Bears and Menu
Style) and beneath balls we have three different colour options. We also have a <div> ready to contain our
content.


                                   Copyright © 2004 DMXzone.com All Rights Reserved
                                           To get more go to DMXzone.com
                                                   Page 2 of 15
                                                                                     Drop Down Menus With Standards
                                                                                                        Matt Machell




Making the Design Nicer to Look At
Create a new CSS file, called menu.css, save it, and attach it to the menu.htm file using the link method. You
can do this quickly by using the attach stylesheet button (circled in red):




and then browsing for the correct stylesheet:




After attaching the stylesheet, you should edit the code so that the styles are for media=all, to avoid
problems with Netscape Navigator 4 (which doesn't support modern CSS standards too well):

<link href="menu.css" rel="stylesheet" type="text/css" media="all" />




                                  Copyright © 2004 DMXzone.com All Rights Reserved
                                          To get more go to DMXzone.com
                                                  Page 3 of 15
                                                                                     Drop Down Menus With Standards
                                                                                                        Matt Machell




Opening up your menu.css file, add the following declarations:

body{
font-family:Arial, Helvetica, sans-serif;
font-size: 80%;
}

#content{
background-color:#E4E4F1;
clear:both;
border: 0.1em solid #000;
margin-top:1em;
padding: 0.5em;
}

#menu{
      padding: 0.2em;
      margin: 0 0 1em 0;
}

#menu li{
list-style: none;
}

.default ul li {
      display: inline;
      margin: 0 0 0 0.4em;
}

Now, if this has been attached properly, you'll get a layout very much like so:




                                  Copyright © 2004 DMXzone.com All Rights Reserved
                                          To get more go to DMXzone.com
                                                  Page 4 of 15
                                                                                      Drop Down Menus With Standards
                                                                                                         Matt Machell




Most of this CSS just adjusts the look of our list and content. This will be the basic appearance that anybody
who doesn't have JavaScript enabled will see.

Note that we've set the body's font size to 80%, which is roughly equivalent to 10 point text, so is a
comfortable size for most people to read. Since it's a percentage based size, this means that the menu items
can scale – an important part of accessibility so anybody with poor sight can view the menu at a size they
find easy to read, by adjusting their font size.

The most important bit of this CSS here is the last one:

.default ul li {
      display: inline;
      margin: 0 0 0 0.4em;
}

This causes the list items in our sub-list to be displayed inline, which means they no longer have line breaks
before and after them, and so flow like they were in a line of text. This keeps our navigation from taking up
too much space at the top of the page.


So Where's My Drop Down Menu?
At this point you're probably starting to wonder when we'll actually see a dropdown menu.

Well, first we'll need to create the styles used in the menu. These will come into play when our JavaScript
switches the class of our menu list from default to vert.

Add the code below to our menu.css file:




                                   Copyright © 2004 DMXzone.com All Rights Reserved
                                           To get more go to DMXzone.com
                                                   Page 5 of 15
                                                                                Drop Down Menus With Standards
                                                                                                   Matt Machell




/* dropdown menu styles */

.vert li{
float: left;
padding: 0;
margin: 0;
border: 0;
}

.vert a{
display: block;
padding: 0.2em;
margin-left: 0.4em;
border: 0.1em solid #000;
color: #00b;
}

.vert a:hover{
background: #E4E4F1;
}

.parent{
      position:relative;
}

.hidden{
display: none;
}

.dropdown{
      display: block;
      margin: 0;
      padding:0;
      position:absolute;
      z-index: 2;
      left: 1.5em;
      top: 0.5em;
      background: #fff;
      border: 0.1em solid #000;
      width: 6.4em;
}

.dropdown li{
margin: 0 !important;
padding: 0 !important;
float: none;
}

.dropdown a{
margin: 0;
border: 0 !important;
width: 6em;
}




                             Copyright © 2004 DMXzone.com All Rights Reserved
                                     To get more go to DMXzone.com
                                             Page 6 of 15
                                                                                        Drop Down Menus With Standards
                                                                                                           Matt Machell




There are quite a lot of styles here, so lets deal with them separately.

The first set of new styles come into play when we switch the menu list to have the class .vert. When we do
this, existing styles that are based off the .default class no longer apply (so we lose the inline list styling from
our .default ul li style).

.vert li{
float: left;
padding: 0;
margin: 0;
border: 0;
}

.vert a{
display: block;
padding: 0.2em;
margin-left: 0.4em;
border: 0.1em solid #000;
color: #00b;
}

.vert a:hover{
background: #E4E4F1;
}

.vert li causes every list item inside the menu to float to the left of the following element. This will give us a line
of items for our top level of the menu.

.vert a causes links within the menu to display as blocks rather than inline. It also adds some basic padding,
margin and border to the item. Again, this ensures our top-level links look like menu buttons.

.vert a:hover creates a rollover state for all the menu items, giving the user some feedback when they're
moused over.

These styles, when applied to the menu, will result in styling the main items like this:




Next we have two independent styles:

.parent{
position:relative;
}

.hidden{
display: none;
}

.parent affects the list item containing our sub-list (the one containing the Balls menu item). It sets it to be
positioned relative. This means that any item within it that is positioned absolutely, will have it's co-ordinates
based on the .parent element, rather than the page as a whole.

                                     Copyright © 2004 DMXzone.com All Rights Reserved
                                             To get more go to DMXzone.com
                                                     Page 7 of 15
                                                                                       Drop Down Menus With Standards
                                                                                                          Matt Machell




.hidden is used to hide the list that contains our dropdown menu items when they're not in use, by setting it to
display: none.

Finally, we have the styles for the dropdown menus themselves:

.dropdown{
      display: block;
      margin: 0;
      padding:0;
      position:absolute;
      z-index: 2;
      left: 1.5em;
      top: 0.5em;
      background: #fff;
      border: 0.1em solid #000;
      width: 6.4em;
}

.dropdown li{
float: none;
}

.dropdown a{
margin: 0 !important;
border: 0 !important;
width: 6em;
}

The .dropdown style is applied to our sub-list when we mouseover its parent. The .dropdown style places the
item absolutely slightly down and to the left of the parent, and above it in the z-index stacking. We set its
width to 6.4em, so that it scales with text size alteration.

.dropdown li styles all the list items within our dropdown menu. Cancelling the float they inherit from being
inside the .vert class.

.dropdown a style sets the dropdown menu's links to be margin-less and border-less. If you're not familiar with
the !important attribute, it essentially flags a declarations as key to that style, so that it doesn't mis-inherit a
property from higher up the cascade. In this case it stops our dropdown items inheriting the border and
margin from the .vert a declaration

Our JavaScript will swap the .hidden and .dropdown styles on our sub-menu list. The image below shows the
sub-list with the two different styles applied:




                                    Copyright © 2004 DMXzone.com All Rights Reserved
                                            To get more go to DMXzone.com
                                                    Page 8 of 15
                                                                                      Drop Down Menus With Standards
                                                                                                         Matt Machell




Applying the Styles with JavaScript
In this section we'll create the code that initialises our menu, swaps the list styles, and adds our dropdown
functionality. The full code is given to start with, then we'll dissect what it's doing.

Firstly, to allow our users to switch menu styles, we need to alter our fourth menu item in our HTML page, so
the line:

<li><a href="#">Menu Style</a></li>

should be altered to:

<li><a href="#" onclick="showhide()" title="switch to accessible menu">Menu
Style</a></li>

This alteration will allow our user to instigate a change from the dropdown style to the normal list style menu.

Now we need to code up the JavaScript behind that showhide() function.

Create a new file called menu.js and attach it to the menu.htm file with the following code inside the
<head> section of the HTML document:

<script language="JavaScript" type="text/JavaScript" src="menu.js"></script>

Then, in the menu.js file add the following code:




                                   Copyright © 2004 DMXzone.com All Rights Reserved
                                           To get more go to DMXzone.com
                                                    Page 9 of 15
                                                                                     Drop Down Menus With Standards
                                                                                                        Matt Machell




if(document.getElementById){
      // is DOM browser

       function showhide(){

       //get menu element

               mainmenu=document.getElementById("menu");

       //set class to vert

               if(mainmenu.className=="default"){
                     mainmenu.className="vert"
                     }
               else{
                     mainmenu.className="default";
                     }

       // find dropdowns and apply/unapply mouseover/out functions

               nodes=mainmenu.childNodes;
               for (var i=0; i<nodes.length; i++){
                     if(nodes[i].className=='parent'){
                           dropdown=nodes[i].getElementsByTagName('ul');
                           if(dropdown[0].className==""){
                                 dropdown[0].className="hidden";
                                 nodes[i].onmouseover= function(){
                                       dropdown[0].className='dropdown';
                                       }
                                 nodes[i].onmouseout= function(){
                                       dropdown[0].className='hidden';
                                       }
                                 }
                           else{
                                 dropdown[0].className="";
                                 nodes[i].onmouseover=null;
                                 nodes[i].onmouseout=null;
                                 }
                           }
                     }
               }

       window.onload=function(){
             showhide();
       }
}

Now there's quite a lot going on in this piece of code, the comments should help, but let's look at it step by
step.

First of all we check if the browser is compatible with the W3C DOM (Document Object Model), using the
following:

if(document.getElementById){
      //code inside snipped
}
                                  Copyright © 2004 DMXzone.com All Rights Reserved
                                          To get more go to DMXzone.com
                                                  Page 10 of 15
                                                                                        Drop Down Menus With Standards
                                                                                                           Matt Machell




document.getElementById only exists in modern standards-compliant browsers, so by testing if it is true, we
test if it exists.

This means in any modern, standards-compliant browser the test will be true and the page will run the code.
Any older browser will ignore it, even if it does support JavaScript. This means we don't have to worry about
incompatibilities in the way we access the style elements via JavaScript, since all our JavaScript goes inside
this test.

Next we declare a function:

        function showhide(){
              mainmenu=document.getElementById("menu");
              if(mainmenu.className=="default"){
                    mainmenu.className="vert"
                    }
              else{
                    mainmenu.className="default";
                    }

The function showhide() is the main part of our script, it switches the menu to dropdown mode when called
and also initialises our dropdowns. Its first call is when the page is loaded, but we'll come to that later.

The first part of the function, shown above does the core of this by switching the class attached to our
#menu id. If it's currently class default it changes to class vert, and vice-versa.

Once our classes are swapped, then all the dependent styles swap too thus styling our menu.

The next part of our code goes through the child elements of the menu (the list items) and looks for one with
the class of parent.

nodes=mainmenu.childNodes;
for (var i=0; i<nodes.length; i++){
                  if(nodes[i].className=='parent'){
                        dropdown=nodes[i].getElementsByTagName('ul');
                        if(dropdown[0].className==""){
                              dropdown[0].className="hidden";
                              nodes[i].onmouseover= function(){
                                    dropdown[0].className='dropdown';
                                    }
                              nodes[i].onmouseout= function(){
                                    dropdown[0].className='hidden';
                                    }
                              }
                        else{
                              dropdown[0].className="";
                              nodes[i].onmouseover=null;
                              nodes[i].onmouseout=null;
                              }
                        }
                  }

If the list item is of class "parent" it finds the array of <ul> elements it contains, and we alter the first one (and
there should only be one in our example). If the element has no class, it sets its class to hidden.

                                     Copyright © 2004 DMXzone.com All Rights Reserved
                                             To get more go to DMXzone.com
                                                     Page 11 of 15
                                                                                      Drop Down Menus With Standards
                                                                                                         Matt Machell




We then do a cool JavaScript trick. The code adds the mouseover and mouseout events to switch the class
when the user moves their mouse over the parent <li>. Now this can seem a bit counter-intuitive if you've not
seen it before, but this is exactly like adding a onmouseover="drop()" function in the HTML, but instead we
add it from within JavaScript, and then instead of naming the function we just attach it directly.

The else clause is used if the <ul> has a class name already. If this is the case then showhide() must have
been run before (the function was called previously on loading for example), so we reverse the procedure
turning our menu back into a normal list, and removing the onmouseover events.

The final part of our script sets the function showhide() to run when the window loads:

       window.onload=function(){
             showhide();
       }

Thus ensuring our menu is built when the document is opened. The next time showhide() is called, it'll turn the
menu back to the non-dropdown version.

A note of caution here.

If you use a window.onload function like this, don't then set an onload function on the <body> element, as
the body one will override the one in the script. This might happen if you later add a Dreamweaver
imageswap behaviour of similar JavaScript that is run based on <body onload="myfunction()">.

Save all your files, and load menu.htm in a browser to see how it works. It should look like this:




Making the Choice Permanent
Obviously, as it stands, the user has to keep clicking the Menu Style link every time the page loads if they
don't want the dropdown menu. Not very usable!

To improve this we can set up our JavaScript to store the users preference in a cookie. Let's look at some
functions to add to our script and how to alter our code to make use of them.




                                   Copyright © 2004 DMXzone.com All Rights Reserved
                                           To get more go to DMXzone.com
                                                   Page 12 of 15
                                                                                       Drop Down Menus With Standards
                                                                                                          Matt Machell




Add the following functions inside the if(document.getElementById) braces

function setcookie(name, value){
var date = new Date();
date.setTime(date.getTime()+(360*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
document.cookie=name+"="+value+expires+"; path=/";
}

function readcookie(cookie){
value="";
cookie+="=";
cookieList= document.cookie;
startLoc= cookieList.indexOf(cookie) + cookie.length;
endLoc= cookieList.indexOf("; ", startLoc);
if(endLoc=="-1"){
      value=cookieList.substring(startLoc);
      }
else{
      value=cookieList.substring(startLoc, endLoc);
      }
return value;

}

The sole purpose of these functions is to store and retrieve information from cookies. The cookies are set using
4 parts. The name of the cookie, the value we're storing, the expiration date and the path (which files can
use the cookie).

setcookie() takes two values, the name of the cookie and its value. It then creates a date 360 days in the
future, which it uses as the expiry date, and creates a cookie with the appropriate data. The cookie is simply
a string of information, which we store in the browser.

readcookie() is more complex. We can't guarantee that there won't be more than one cookie associated
with the site, and they'll all be stored in the same document.cookie string. So we have to do some string
manipulation to find our cookie in amongst the others and if necessary slice it out before returning the value
of it.

Since cookies aren't the core of this article, I've glossed over things slightly here, but if you want to learn more
about cookies, check out Tom Dell'Aringa's Introduction to Cookies article.


Storing our User's Preference
The important part of the functions you just created is that they allow us to store the users preferences. Every
time the menu mode is changed, we'll use our setcookie() function to set a cookie which is either an empty
string or "default". When a page containing the script is loaded, we check to see if cookie is empty (and
hence the user wants the dropdown) and if so, we run our showhide() function.




                                    Copyright © 2004 DMXzone.com All Rights Reserved
                                            To get more go to DMXzone.com
                                                    Page 13 of 15
                                                                                      Drop Down Menus With Standards
                                                                                                         Matt Machell




Our full code now looks something like this (alterations in bold):

if(document.getElementById){
      // is DOM browser

       function showhide(){
             mainmenu=document.getElementById("menu");
             if(mainmenu.className=="default"){
                   mainmenu.className="vert";
                   setcookie("menu", "");
                   }
             else{
                   mainmenu.className="default";
                   setcookie("menu", "default");
                   }
             nodes=mainmenu.childNodes;
             for (var i=0; i<nodes.length; i++){
                   if(nodes[i].className=='parent'){
                         dropdown=nodes[i].getElementsByTagName('ul');
                         if(dropdown[0].className==""){
                               dropdown[0].className="hidden";
                               nodes[i].onmouseover= function(){
                                     dropdown[0].className='dropdown';
                                     }
                               nodes[i].onmouseout= function(){
                                     dropdown[0].className='hidden';
                                     }
                               }
                         else{
                               dropdown[0].className="";
                               nodes[i].onmouseover=null;
                               nodes[i].onmouseout=null;
                               }
                         }
                   }
             }

       window.onload=function(){
       if(readcookie("menu")==""){
             showhide();
             }
       }
       function setcookie(name, value){
       var date = new Date();
       date.setTime(date.getTime()+(360*24*60*60*1000));
       var expires = "; expires="+date.toGMTString();
       document.cookie=name+"="+value+expires+"; path=/";
       }




                                   Copyright © 2004 DMXzone.com All Rights Reserved
                                           To get more go to DMXzone.com
                                                   Page 14 of 15
                                                                                     Drop Down Menus With Standards
                                                                                                        Matt Machell




       function readcookie(cookie){
       value="";
       cookie+="=";
       cookieList= document.cookie;
       startLoc= cookieList.indexOf(cookie) + cookie.length;
       endLoc= cookieList.indexOf("; ", startLoc);
       if(endLoc=="-1"){
             value=cookieList.substring(startLoc);
             }
       else{
             value=cookieList.substring(startLoc, endLoc);
             }
       return value;

       }
}



Summary
So we have a more elegant dropdown menu solution, the code is reasonably short, it works with a variety of
browsers and degrades gracefully if the user doesn't have the correct scripting, or doesn't have a mouse.
With a bit of alteration we can slot this menu into any color scheme (by altering the CSS).

Similarly, you don't necessarily have to put the link to swap the menu in the menu itself, it could be in a
preferences area of your design (see Rachel Andrew's CSS: User-customisable Site series for more details).
Another simple enhancement would be to use some CSS background images to style the parent <li> with
arrows, or items with appropriate symbols.




                                  Copyright © 2004 DMXzone.com All Rights Reserved
                                          To get more go to DMXzone.com
                                                  Page 15 of 15

								
To top