CSS Menus ...

One of the best resources on the web for CSS-based menus (or indeed anything to do with CSS) is CSS Play where there are umpteen examples ranging from the simple to the downright exotic. Great care is taken to ensure cross-browser compatability but on the downside finding the actual code buried in the html of each page can prove too challenging for less experienced users (this despite the pretty clear labelling, I think some folks just glaze over at the mass of code). There is also an issue with some of the earlier, simpler menus which are based on definition lists - rather than the unordered lists which are now considered the norm. Recently the author of CSS Play launched a new site CSS Menus which addresses these concerns to some extent. A more accessable, if less well tested and less varied, resource is the CSS area of Dynamic Drive where the code is presented in impossible-to-miss panels on the same page.

One thing to bear in mind, especially with the Dynamic Drive examples, is that the use of a "current" style for a menu item relating to the current page requires a little bit of extra work when using server-side includes for your menu. This might be important if you have many pages on the site and is likely essential if you are running a CMS (content management system / blogger such as Wordpress, Joomla or Drupal). I'll address that further down this page.

A CSS Menu Deconstructed ...

The menu on this page was inspired by the DD Blue Blocks Menu at Dynamic Drive although I rewrote it from scratch in what I think is a more logical fashion (one list rather than multiple lists in multiple divs). Here is how it is put together:

The HTML looks like this (I've truncated the list to avoid filling the page up with unneccessary text and taken out some id tags for now):

<ul>
  <li class="menuhead">
    Web Design
  </li>
  <li>
    <a href="index.php">Home</a>
  </li>
  <li>
    <a href="onmenus.php">Menus</a>
  </li>
  <li class="divider">
    Other
  </li>
  <li>
    <a href="contact.php">Contact</a>
  </li>
</ul>

That is simply an unordered list. Some of the list items are plain text (and have classes associated with them) - those will be the dividers - while some are links and will form the working part of the menu, taking the reader elsewhere in the site. As written, the menu would be pretty boring - it would look something like this:

  • Web Design
  • Home
  • Menus
  • Links
  • Other
  • Contact

So we have to get styling with CSS. First we strip out the bullet points and inherited margins and paddings (should there be any).

#leftcolumn ul{
  list-style-type:none;
  margin:0;
  padding:0;
}

Next lets give the list top and divider some style. The menu is in the left hand column so we'll use that id. I would prefer to be calling the styles via a class so that we could use more than one menu but that creates some problems with the priorities of the styles in Internet Explorer. The following code sets the font and background colours and sets a border around the left, right and bottom sides (we don't need a top border working down the list as the bottom border from above divides the list items). There is also the option to give the top item a top border but the current style looks better without.

#leftcolumn li.menuhead,
#leftcolumn li.divider{
  color:black;
  background-color:#f3aea9;
  width:144px;
  padding:2px;
  font-weight:bold;
  border-right:1px solid white;
  border-left:1px solid white;
  border-bottom:1px solid white;
}

#leftcolumn li.head{
  /*border-top:1px solid white; use this if you need a border
  at the top of the menu*/
}

Then to style the actual links we have the following:

#leftcolumn li a{
  display:block;
  color:black;
  background-color:#fadeda;
  width:140px;
  padding:2px;
  padding-left:6px;
  border-right:1px solid white;
  border-left:1px solid white;
  border-bottom:1px solid white;
  text-decoration:none;
}

#leftcolumn li a:hover{
  background-color:#dda0dd;
}

The link is given a contrasting background and similar widths and padding to fit into the 150px wide left column. In Firefox you don't need the width but it is required in IE to make the whole rectangular area clickable - display:block does the rest of the work there as explained in this article on CSS Tricks. There is a separate color set for the hover state so that the reader can see that the link is live.

"Current" Menu Items

So far we have the code for a two colour menu with a third colour for the hover state. However if you look at the menu on this page you will see a fourth colour indicating which page we are currently on. This is a fairly common theme and you can see many examples on the Dynamic Drive site referenced above. Typically this effect by editing the menu on each page so that the relevant list item has an "current" class. Something like this:

  <li class="current">
    <a href="index.php">Home</a>
  </li>

You could then set a different colour for that class in the stylesheet. This is all well and good but can't be applied in a situation where the menu comes from a server side include file to allow simpler maintenance (where one file codes for the menu on every page on the site - see the separate "PHP include" page when it comes out). In that scenario we need some sort of dynamic assignment of "current" class that is independant of the menu-containing file. The trick here is to place ids in the body tags of individual pages and ids for each menu item, thus:

<body id="index">
<ul>
<li class="head">
  Web Design
</li>
<li id="menu_index">
  <a href="index.php">Home</a>
</li>
<li id=menu_onmenus>
  <a href="onmenus.php">Menus</a>
</li>
<li class="divider">
  Other
</li>
<li id="menu_contact">
  <a href="contact.php">Contact</a>
</li>
</ul><br>

Now, in our stylesheet we set things up so that a different background colour is displayed only when both the page id and the corresponding menu id match up. Like this:

#index #menu-index a,
#onmenus #menu-onmenus a,
#links #menu-links a, 
#contact #menu-contact a{
  background-color:#f6ccda;
}

One last thing is that we have to re-do the hover state for these combinations too:

#index #menu-index a:hover,
#onmenus #menu-onmenus a:hover,
#links #menu-links a:hover, 
#contact #menu-contact a:hover{
  background-color:#f6ccda;
}

I'd like to have been the originator of such a clever idea but of course it is a well established technique. I first saw it here, some googling will bring forth many other examples.