Need some help?

I'm usually available for small jobs or problem solving with jQuery or css, at reasonable rates. Just get in touch.

Web Hosting

We recommend Clook for web hosting. UK based, great service and great value.

Building a css vertical expanding menu with flyouts – stage 2

Click here for Part 1

OK, now to add the second level menu to the html. For the purposes of this I’ll add a couple of menu items under each of “Blog” and “Websites”:

html
<div id="nav-menu">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Blog</a>
	<ul>
	<li><a href="#">Blog 1</a></li>
	<li><a href="#">Blog 2</a></li>
	</ul>
</li>
<li><a href="#">Websites</a>
	<ul>
	<li><a href="#">Websites 1</a></li>
	<li><a href="#">Websites 2</a></li>
	</ul>
</li>
<li><a href="#">Photos</a></li>
</ul>
</div>

Note that the new entries need to be enclosed within the existing <li> tags. So this gives us:

Now the second level menu items are all showing as expected (I’ll hide them a bit later on). First let’s make them look a bit different so it’s clear which level is which.

css

#nav-menu ul
 {list-style-type:none;
  margin:0px;
  padding:0px}

#nav-menu ul a
{text-decoration:none;
 border:1px solid #303030;
 width:170px;
 display:block;
 text-align:center;
 font-size:14pt;
 line-height:2em;
 background:url(Images/Buttons/Button_top.gif) repeat-x left;
 font-family:Arial, Helvetica, sans-serif;
 color:white}

#nav-menu ul ul li a
{border:1px solid #888888;
 border-bottom: none;
 font-size:12pt;
 line-height: 1.6em;
 color:#303030;
 background-color:#a5a5a5;
 background-image:none;}

So here I’ve applied slightly different styling to the second level menu items. I’ve applied a different colour border, a different font-size, line-height and text colour, and this time I’ve applied a plain background colour (light grey #303030) instead of the background image.

A couple of things to note here. I don’t need to re-apply the width, display:block and text-align at this stage because they are inherited from the earlier declarations for #nav-menu ul a.

However, because the background-image will be inherited in the same way, and I don’t want this, I have to specifically define background-image:none for my second level menu.

The last point is a cosmetic one really. If my second level menu items have borders all round, I’ll get two borders between the menu items which looks a bit ugly, so I set no bottom border by the border-bottom:none statement.

So I now have:

Right, this looks something like what I want but I’ve still always got the second level menu displayed. I’m going to change this so the second level is only displayed when a first level page is displayed – so I only see the “Blog 1 ” link when I’m on a blog page. First off I’ll going to hide all the second level menus.

css

#nav-menu ul
 {list-style-type:none;
  margin:0px;
  padding:0px}

#nav-menu ul a
{text-decoration:none;
 border:1px solid #303030;
 width:170px;
 display:block;
 text-align:center;
 font-size:14pt;
 line-height:2em;
 background:url(Images/Buttons/Button_top.gif) repeat-x left;
 font-family:Arial, Helvetica, sans-serif;
 color:white}

#nav-menu ul ul
{display:none} 

#nav-menu ul ul li a
{border:1px solid #888888;
 border-bottom: none;
 font-size:12pt;
 line-height: 1.6em;
 color:#303030;
 background-color:#a5a5a5;
 background-image:none;}

The browser now displays, as expected:

Here’s the clever bit. I’m now going to display the second level only on the appropriate pages. First I need to identify the pages in the html, and I can do this by assigning a class to the body tag on each page. So, on the Blog pages I assign the page a class in the body tag:

html

<body class="blog">
and similarly for the website pages:
html

<body class="web">
Note that I leave the Home Page and the Photo pages unchanged, as in this example there’s no second level pages for these:
html

<body>

Next I need to mark up the html controlling the menu with matching classes:

html

<div id="nav-menu">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Blog</a>
	<ul class="blog">
	<li><a href="#">Blog 1</a></li>
	<li><a href="#">Blog 2</a></li>
	</ul>
</li>
<li><a href="#">Websites</a>
	<ul class="web">
	<li><a href="#">Websites 1</a></li>
	<li><a href="#">Websites 2</a></li>
	</ul>>
</li>
<li><a href="#">Photos</a></li>
</ul>
</div>

Note that it’s the second level <ul> tags to which I assign the class. Now I can add a line to the css so that the menu items are displayed only when I want them to be. The css looks like this:

css

#nav-menu ul
 {list-style-type:none;
  margin:0px;
  padding:0px}

#nav-menu ul a
{text-decoration:none;
 border:1px solid #303030;
 width:170px;
 display:block;
 text-align:center;
 font-size:14pt;
 line-height:2em;
 background:url(Images/Buttons/Button_top.gif) repeat-x left;
 font-family:Arial, Helvetica, sans-serif;
 color:white}

#nav-menu ul ul
{display:none} 

body.blog #nav-menu ul ul.blog, 
body.web #nav-menu ul ul.web
{display:block}

#nav-menu ul ul li a
{border:1px solid #888888;
 border-bottom: none;
 font-size:12pt;
 line-height: 1.6em;
 color:#303030;
 background-color:#a5a5a5;
 background-image:none;}

To explain this, what I’m saying here is that if the page has a class of “blog” , defined by the statement body.blog and the second level menu has a class of “blog”, defined by #nav-menu ul ul.blog then the menu should be displayed (display:block). A similar statement applies to the web menu.

Now, if we look at the Home Page it looks like this:

And the Blog pages look like this:

And the Website pages look like this:

So now I have a vertical expanding menu using css only. This was my original aim, but when I was testing I thought it would aid the navigation if you could get quickly to a second level page either from the Home page or from a different page. If you’re still interested, read on:

Click here for Part 3

One response to “Building a css vertical expanding menu with flyouts – stage 2”

  1. Mona says:

    Thanks a lot, it’s very helpful

Useful? Interesting? Leave me a comment

I've yet to find a way of allowing code snippets to be pasted into Wordpress comments - so if you're trying to do this you'd be better off using the contact form.