ARTICLES

WEB DEVELOPMENT ARTICLES

Mostly CSS Multi-level Menus - Part I

In this article we learn how to produce multi-level CSS menus using valid XHTML and minimal JavaScript. Our goal was the simplest approach possible so you understand exactly what's going on instead of just cutting and pasting in code. We assume you know HTML and CSS.

In part I we will start with vertical menus that expand when clicked on. The first step is to create our links in XHTML. We should be able to use the same XHTML for both vertical and horizontal menus.

<div id="css_vert"> <div class="link"> <a href="#">Plants</a> <div class="submenu" id="plants"> <div class="link"> <a href="#">Trees</a> </div> <div class="link"> <a href="#">Vegetibles</a> </div> </div> </div> <div class="link"> <a href="#">Animals</a> <div class="submenu" id="animals"> <div class="link"> <a href="#">Cats</a> <div class="submenu" id="cats"> <div class="link"> <a href="#">Lions</a> </div> <div class="link"> <a href="#">Tigers</a> </div> </div> </div> <div class="link"> <a href="#">Dogs</a> </div> </div> </div> <div class="link"> <a href="#">Rocks</a> </div> </div>

Next we should add this to our style sheet. This makes the submenus indented and a different color, but you can do whatever you want with them.

div.submenu { margin-left: 10px; } div.link div.link a { text-decoration: none; color: #C90; font-size: 9pt; }

So far our links look like this:

Now we want to make the submenus dissapear unless clicked on. Changing the CSS as follows makes this happen. A display of 'none' means that the HTML will not be rendered by the browser.

div.submenu { margin-left: 10px; display: none; }

Now we need to add a wee bit of JavaScript to make the submenus expand when we want them. The function gets passed the element id and sees what is the current display style for that element. If its 'none' it changes it back to 'block' so it can be seen. If its 'block' it changes it to 'none' to remove it.

<script type="text/javascript" charset="utf-8"> function submenudisplay(submenuid) { submenu = document.getElementById(submenuid); if (submenu.style.display == "block") { submenu.style.display = "none"; } else { submenu.style.display = "block"; } } </script>

We also need to add a javascript event to each link that opens a submenu. Take out the onclick="return(false);" if you want the link to go somewhere.

<div id="css_vert"> <div class="link"> <a href="#" onclick="submenudisplay('plants'); return(false);">Plants</a> <div class="submenu" id="plants"> <div class="link"> <a href="#" onclick="return(false);">Trees</a> </div> <div class="link"> <a href="#" onclick="return(false);">Vegetibles</a> </div> </div> </div> <div class="link"> <a href="#" onclick="submenudisplay('animals'); return(false);">Animals</a> <div class="submenu" id="animals"> <div class="link"> <a href="#" onclick="submenudisplay('cats'); return(false);">Cats</a> <div class="submenu" id="cats"> <div class="link"> <a href="#" onclick="return(false);">Lions</a> </div> <div class="link"> <a href="#" onclick="return(false);">Tigers</a> </div> </div> </div> <div class="link"> <a href="#" onclick="return(false);">Dogs</a> </div> </div> </div> <div class="link"> <a href="#" onclick="return(false);">Rocks</a> </div> </div>

Now our links look like this. Try it!

There is still one problem left to solve. If you actually follow a link on a submenu to the next page, the javascript reloads and the submenu will be gone as before. For example, suppose you click on the Lions link. If you want to keep the animals and cats submenus both expanded you can add the following CSS to the lion page.

<style type="text/css"> div#animals, div#cats { display: block; } </style>

The same principle can be applied to horizontal menus that expand another horizontal menu, but what if we want a menu that displays submenus that appear to 'float' over our page rather than expand it? Read Part II to find out.