ARTICLES

WEB DEVELOPMENT ARTICLES

Mostly CSS Multi-level Menus - Part II

In Part I we looked at using the CSS display property to expand and collapse menus when clicked. Now we are going to look at the CSS visibility property to show and hide floating menus. Again we want to use valid XHTML and CSS with minimal JavaScript.

We are going to use the exact same XHTML as we used in part one with some changes to the CSS and JavaScript. Here is the XHTML, just as before.

<div id="css_horiz"> <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>

Now we modify our style sheet to include the following. Its quite a bit more complicated than in part one. First you will notice we want the top level divs to be 'inline' which basically makes the horizontal. We also have to explicitly tell them to be position 'relative' so that the submenus can be 'absolute' based off of their container. The z-index property tells the browser to make the content appear to float above the lower levels, and the top and left positions tell the browser where to position the layer relative to the containing div.

div.link { display: inline; position: relative; padding-right: 15px; } div.submenu { z-index: 5; position: absolute; top: 15px; left: 20px; display: block; background-color: #D9DDCD; width: 175px; border: 1px solid #333; visibility: hidden; } div.submenu div.submenu { z-index: 10; position: absolute; top: 0px; left: 175px; display: block; background-color: #D9DDCD; width: 175px; border: 1px solid #333; } div.submenu div.link { display: block; background-color: #D9DDCD; padding-right: 0px; border-bottom: 1px dotted #333; } 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 visible when we hover over them. Here is the JavaScript that makes it work. The first parameter we pass to this function is the ID of the element we wish to make visible. The second parameter is the level of the menu (0 is the top level). An array is populated with the ID of the levels that were made visible, so we can make them invisible if another menu is mouse over.

<script type="text/javascript" charset="utf-8"> var lastid = new Array(); var level = 0; function submenupop(submenuid,level) { for (i=level; i<lastid.length; i++) { if (lastid[i]) { document.getElementById(lastid[i]).style.visibility = "hidden"; } } if (submenuid != '') { submenu = document.getElementById(submenuid); submenu.style.visibility = "visible"; lastid[level] = submenuid; } } </script>

We also need to add a javascript event to each link, wether or not it opens a submenu (except for the lowest level links). Again take out the onclick="return(false);" if you want your links to go somewhere.

<div id="css_horiz"> <div class="link"> <a href="#" onmouseover="submenupop('plants',0);" onclick="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="#" onmouseover="submenupop('animals',0);" onclick="return(false);">Animals</a> <div class="submenu" id="animals"> <div class="link"> <a href="#" onmouseover="submenupop('cats',1);" onclick="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="#" onmouseover="submenupop('',1);" onclick="return(false);">Dogs</a> </div> </div> </div> <div class="link"> <a href="#" onmouseover="submenupop('',0);" onclick="return(false);">Rocks</a> </div> </div>

Our links look the same but now you can mouse over them and get to the submenus. Try it!.

We wanted the links stay open if you mouse off of them, unless you mouse over another menu. This behavior is very similar to what you experience in your OS applications. If you navigate to a submenu all the menus are reset as expected. You could easily adapt this to vertical menus as well.

This concludes our two part series on creating valid CSS menus with minimal JavaScript. Feel free to use this code in your own site and link to these articles.