JavaScript/CSS Tab Menu With Sub-Navigation

Intro: JavaScript/CSS Tab Menu With Sub-Navigation

In this instructable, I'll show you step-by-step how to create a JavaScript/CSS based tab menu with a rollover effect and a changing sub-navigation menu. Some basic JavaScript ans CSS knowledge is helpful, but not required, since I'll provide all the code.

This code has been tested in FireFox ans IE6/7. I haven't had the opportunity to test it on a Mac, but it should work fine.

What you need:
- A graphics editor (Photoshop, The GIMP, Pain Shop Pro, whatever)
- A text editor (like Crimson Editor or Notepad)
- Caffeine (optional)

Step 1: Making the Images

First, we need to decide on the style for our menu and create the images accordingly. I'm not going to go into a lot of detail on this, since the real magic behind the menu is in the code and not the graphics, but we will need a few basic images to help tidy up the appearance of our menu (though you could technically skip this step and use solid colors in your CSS).

This is the background image for our sub-nav menu (the bar directly below the tabs). The only technical requirement here is that the image be 25px in height, in order to work with the CSS I'm supplying.

This small image is essentially just a 1-2px wide vertical line, again, 25px in height, that will serve as a separator between our sub-nav elements. Hint: Make the image 2px side and use a light line next to a dark line to create a beveled look.

This is the background image for our main menu tabs. My tabs are 90px wide and 29px high (oops.... I was off by one).

Of course, if you don't feel like making your own images, you can always grab these....

Step 2: The HTML Mark-Up

Our markup for the menu is fairly straightforward. We're going to create a container div that will hold an unordered list containing our main menu items. Below that, we'll make another container div and within it, we'll put unordered lists for each sub-menu.

Like so:
[nav]  [main menu]  [sub-nav]    [sub-nav menus]  [/sub-nav][/nav]

So let's build the mark-up....

Our document head (where we import our JavaScript and CSS):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" ""><html><head>	<title>Javascript & CSS Tab Menu with Sub-navigation</title>	<style type="text/css">		@import "css/menu.css";	</style>	<script type="text/javascript" src="js/menu.js"></script></head>

The body tag, wherein we initialize the menu (IMPORTANT):
<body onload="navMenu()">

The menus themselves (structured as illustrated above):
<div id="nav">	<ul id="tabBar">		<li><a href="/index.html">Home</a></li>		<li><a href="/about.html" rel="menutrigger" name="about">About</a></li>		<li><a href="/work.html" rel="menutrigger" name="work">Our Work</a></li>		<li><a href="/contact.html">Contact</a></li>	</ul>	<div id="subNav">		<ul id="aboutNav">			<li><a href="/staff.html">Our Staff</a></li>			<li><a href="/facilities.html">Facilities</a></li>			<li><a href="/certifications.html">Certifications</a></li>		</ul>		<ul id="workNav">			<li><a href="/programs.html">Programs</a></li>			<li><a href="/events.html">Events</a></li>		</ul>	</div></div>

Close the body and the rest of the page as well:

Step 3: The JavaScript

Now let's move on to the JavaScript that will control the showing and hiding of our sub-menu items. We want the items in our sub-menu to change on mouse click, based on which parent tab was clicked.

First, we'll start off by writing a function to hide all of the menu items within our "subNav" container.

The below function gets a list of all UL elements within the subNav ID, then loops through that list and sets each element's display property to 'none'

function hideItems() {	var list = document.getElementById("subNav").getElementsByTagName("ul");	for(i=0;i<list.length;i++) {		list[i].style.display="none";	}}

Alright, now let's start writing the function to display the sub-menu items.

function navMenu() {	if (!document.getElementsByTagName){ return; }	var anchors = document.getElementsByTagName(&aposa&apos);

The first line of our function is a failsafe that simply tells the browser to follow the link if it doesn't support the 'getElementsByTagName' function.

The second line, similar to the function above, gets a list of all links and puts them into an array called 'anchors'

	for (var i=0; i<anchors.length; i++){		var anchor = anchors[i];					var relAttribute = String(anchor.getAttribute(&aposrel&apos));

Now we start to loop through our 'anchors' array. Here, we grab the value of the 'rel' attribute for each link as we come to it.

		if (relAttribute.toLowerCase().match(&aposmenutrigger&apos)){			anchor.onclick = function() { 

Now we check to see if that 'rel' value (which we stored as 'relattribute') is equal to 'menutrigger' and if so, we're going to trigger our on-click event.

				var nameAttribute = this.getAttribute(&aposname&apos) + "Nav";				var thismenu = document.getElementById(nameAttribute);				hideItems();"inline";				return false;			}		}	}}

First, we append the text 'Nav' to the end of the link's name attribute. Now our new nameAttribute value matches the name of the sub-nav menu we'll be affecting!

So then we grab that sub-menu and assign it to the 'thismenu' variable.

Now we hide all of our previously displayed sub-menus by calling the 'hideItems()' function we created earlier.

Then, we set the current sub-menu's display property to 'inline' to make it visible.

Finally, tell the browser not to follow the main menu link (that we just clicked) and close out all of our open brackets.

Step 4: The CSS

Finally, we need to create our CSS to style the menu. You'll probably want to play with dimensions and what have you when creating your own nav bar, so that it matches the width of your layout. For now, though, I'm creating a tab menu that's 600px wide. The height of the menu bar is 54px (25px for our sub-nav + 29px for our tabs).

#nav {	width:600px;	height:54px;	margin:0;	padding:0;}

Next, we'll style all of the text within our nav/sub-nav: This is purely cosmetic. It centers all of the text, makes it white, sets the font, and gets rid of the link underlines.

#nav * {	text-align:center;	color:#fff;	font-weight:bold;	text-decoration:none;	font-family:arial, helvetica, sans-serif;	font-size:9pt;}

Next, we'll get rid of all of the margins, padding and bullets from all of our lsits.

#nav ul, #nav ul li {	margin:0;	padding:0;	list-tyle-type:none;}#nav ul li { display:inline; }

Float our main menu tabs to the right side of the nav bar:

ul#tabBar { float:right; }

Now we'll style our main nav tabs, including their standard and hover states: Note that by changing the line-height on the hover state, we make the tab "pop up."

ul#tabBar li a {	display:block;	float:left;	width:90px;	height:29px;	line-height:39px;	background:url(../imgs/tab_bg.jpg) 0 10px no-repeat;	border-left:4px solid #fff;	overflow:hidden; /* fixes IE display bug */}ul#tabBar li a:hover {	line-height:29px;	background:url(../imgs/tab_bg.jpg) top left no-repeat;}

Now we set the styles for our sub-nav lists: We want to hide the sub-nav lists by default, make sure they clear they get positioned below the main tabs, and we want to float them to the left of our menu bar and set the background. Tor the sub-nav container itself we use the 'nav_bg.jpg' file and then for the sub-nav list, we set the background to the 'subnav_separator.jpg' file, and make sure it's positioned to the left and doesn't repeat.

#subNav ul { display:none; }#subNav {	clear:both;	height:25px;	background:url(../imgs/subnav_bg.jpg) top left repeat-x;	padding-left:100px;}#subNav ul {	float:left;	background:url(../imgs/subnav_separator.jpg) top left no-repeat;}

Finally, we style the links: This is very straightforward. We're just setting the link dimensions, floating each link to the left, setting the text alignment and the background. Notice how we set the 'nav_separator.jpg' as the background and position it on the right edge of the link.

	display:block;	float:left;	width:90px;	text-align:center;	line-height:25px;	background:url(../imgs/subnav_separator.jpg) top right no-repeat;}#subNav li a:hover { color:#cde7ff; }

That finishes up the menu! I've attached the full source for you to play with.



    • Fix It! Contest

      Fix It! Contest
    • Audio Contest 2018

      Audio Contest 2018
    • Tiny Home Contest

      Tiny Home Contest

    4 Discussions


    10 years ago on Introduction

    Kelli, I was trying to re-create it and the sub-menu part doesn't work. The only thing that was strange - CSS doesn't have a style for ID aboutNav and workNav. Still it should work, but.... Give me a hint where I should look.... Thanks!


    I love you! I've been trying to work out a menu like this for some time now. Thank you so much!


    11 years ago on Introduction

    Cool, very useful for us web design noobz.....I hate that word....but I had to use it once in my life!