Building a css vertical expanding menu with flyouts – stage 2
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:
Thanks a lot, it’s very helpful