Tutorials Web Development

Color-Coded Dropdown Navigation with Submenus

5/5 (2)

Dropdown menus have been around for years and they've served their purpose quite well. Very much like old-yet-functional technology, dropdown menus continue to support users from all browsers and operating systems. The major differences have come about from a change in newer trends with jQuery and CSS3. I recently found a great example on the Tuts+ website and decided to recreate a similar menu structure.



In this tutorial I want to demonstrate how you can build a multi-tier dropdown menu with jQuery. The most basic solution is to create a menu with one dropdown list. But it's possible to nest two or even three menus into a list to create sub-menu flyouts. I'll be using color-coded menu links following Tuts+ to replicate a similar interface. Take a peek at my sample demo to get an idea of the final product.

Live Demo - Download Source Code

Getting Started

Creating the menu is primarily within the domain of CSS but the dropdown effect is created using jQuery. It is possible to build this entirely in CSS but only modern browsers would support that functionality. I've chosen jQuery because it's more efficient and universally supported.

1
2
3
4
5
6
7
8
<!doctype html>
 
  Color-Coded Dropdown Nav Menu - Template Monster Demo
 
 
 
 
  <script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>

Grab a local copy of the jQuery library and include this in the document header. Also create a separate stylesheet named styles.css which will contain all the page structure and menu design.

For the page itself I've created an outer wrapper using the ID #wrapper. Inside is an unordered list with the ID #menu. This main menu container holds all the primary links, most of which also contain sub-menus. The "categories" link includes a sub-sub-menu which holds sub-categories. This is what the HTML structure looks like:

Each of the internal category links have an additional class name. This is how we can setup unique colors which take over the link and sub-menu while the user is hovering. It's all very straightforward and each nested UL element is contained within a parent list item.

Designing with CSS

At the top of my stylesheet you'll notice a large block of page resets. These remove default browser settings like margin/padding and font sizes to create a uniform blank slate.

Below the resets I've setup a primary page structure for the main elements. An outer nav element spans the entirety of the page using a dark blue background. Inside is the #wrapper div which centers content and holds the main navigation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/** page structure **/
nav {
  display: block;
  width: 100%;
  height: 70px;
  background: #384958;
}
 
.wrapper { 
  display: block;
  margin: 0 auto;
  width: 750px;
}
 
#menu {
  display: block;
  position: relative;
  z-index: 99;
}

In the top-tier menu we have all the main links which are displayed at all times. Each anchor link is a block-level element so it takes up more space for users to hover. Notice the 2nd tier menu has a z-index property of -1. This will ensure that the dropdown appears beneath the main blue navbar to hide excessive padding or drop shadows.

These 2nd tier menus are targeted as #menu li ul because they're the 2nd ul element. I'm using absolute positioning so they'll fit relative to the parent list item while keeping the z-index property in check. Now we get into the 3rd tier menu which is a flyout display of extra categories.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#menu li {
  display: block;
  float: left;
 
}
#menu li a {
  display: block;
  position: relative;
  float: left;
  padding: 0 35px;
  font-size: 1.5em;
  line-height: 70px;
  font-weight: bold;
  text-decoration: none;
  color: #f5f5f5;
}
#menu li a:hover, #menu li a.active {
  background: #fff;
  color: #2c343b;
}
 
#menu li ul {
  display: none;
  position: absolute;
  top: 70px;
  width: 200px;
  background: #fff;
  z-index: -1;
  -webkit-box-shadow: 0 2px 7px rgba(0,0,0,0.45);
  -moz-box-shadow: 0 2px 7px rgba(0,0,0,0.45);
  box-shadow: 0 2px 7px rgba(0,0,0,0.45);
}
#menu li ul li {
  display: block;
  width: 200px;
}
#menu li ul li a {
  display: block;
  float: none;
  color: #4e5b67;
  font-size: 1.35em;
  line-height: 50px;
  padding: 0 15px;
}
#menu li ul li a:hover {
  background: #384958;
  color: #fff;
}

These appear as the 3rd ul element in the navigation. You'll notice that I'm actually targeting the 2nd tier UL with an additional class of .expanded. This is because of the drop shadow effect which needs to appear like one big block - so instead of creating 2 different menus I'm just making the dropdown menu wider. This gives the illusion of a flyout menu which is connected to the original dropdown.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#menu li ul.expanded {
  width: 400px;
}
#menu li ul.expanded li { margin-right: 200px; }

 
 
#menu li ul li ul {
  display: none;
  position: absolute;
  left: 200px;
  top: 0;
  height: 100%;
  background: none;
  -webkit-box-shadow: none;
  -moz-box-shadow: none;
  box-shadow: none;
}
#menu li ul li ul li a { color: #fff; }
#menu li ul li ul li a:hover { text-decoration: underline; }

#menu li ul li.purple a:hover, #menu li ul li.purple a.active { background: #4f4c83; color: #fff; }
#menu li ul li.purple ul { background: #4f4c83; }

#menu li ul li.green a:hover, #menu li ul li.green a.active { background: #65834c; color: #fff; }
#menu li ul li.green ul { background: #65834c; }

#menu li ul li.aqua a:hover, #menu li ul li.aqua a.active { background: #4c7983; color: #fff; }
#menu li ul li.aqua ul { background: #4c7983; color: #fff; }

#menu li ul li.red a:hover, #menu li ul li.red a.active { background: #834c4c; color: #fff; }
#menu li ul li.red ul { background: #834c4c; }

#menu li ul li.blue a:hover, #menu li ul li.blue a.active { background: #4d6899; color: #fff; }
#menu li ul li.blue ul { background: #4d6899; }

#menu li ul li.gold a:hover, #menu li ul li.gold a.active { background: #97944c; color: #fff; }
#menu li ul li.gold ul { background: #97944c; }

Absolute positioning is also used for the 3rd tier menu which is fixed at the very top of the nav container. This means it will always be directly parallel with the original dropdown so it just looks like one large menu.

Also the parent list item can take one of several classes like .purple, .green, or .aqua. You can also create your own color class by mimicking the same template with a different background color.

Dropdown Menus with jQuery

Finally we get to the pièce de résistance of this beautiful navigation that makes the whole thing sparkle. We only need a couple event handlers related to the 2nd tier and 3rd tier menus. But first I should clarify a small block of code located at the very start of my JavaScript:

1
2
3
$('a[href="#"]').on('click', function(e){
  e.preventDefault();
});

This selector matches every anchor link using the href="#" attribute. A link using the hash symbol leads nowhere and is generally meant for wireframing or demos like my example. But when a user clicks the hash symbol it gets loaded into the browser window - kind of annoying and not really useful.

This block of jQuery stops that from happening. It's not necessary to keep this block of code if you remove all the blank links but it does come in handy when building small demo pages.

1
2
3
4
5
6
7
$('#menu &gt; li').on('mouseover', function(e){
  $(this).find("ul:first").show();
  $(this).find('&gt; a').addClass('active');
}).on('mouseout', function(e){
  $(this).find("ul:first").hide();
  $(this).find('&gt; a').removeClass('active');
});

First up is the original dropdown menu. When a user hovers any list item contained within #menu we display the very first sub-menu list. This is selected through ul:first which is a CSS pseudo-class targeting the first child. The hovered link also gets a class of .active to keep it highlighted even if the user moves their mouse down onto links in the dropdown menu.

During a mouseout event the menu will hide and the parent anchor link is no longer active. We'll find a very similar approach used for the sub-sub menu but with a little more detail.

1
2
3
4
5
6
7
8
9
10
11
$('#menu li li').on('mouseover',function(e){
  if($(this).has('ul').length) {
    $(this).parent().addClass('expanded');
  }
  $('ul:first',this).parent().find('&gt; a').addClass('active');
  $('ul:first',this).show();
}).on('mouseout',function(e){
  $(this).parent().removeClass('expanded');
  $('ul:first',this).parent().find('&gt; a').removeClass('active');
  $('ul:first', this).hide();
});

One immediate change you'll notice is the logic check for $(this).has('ul').length. In plain English this says "if the hovered link has another sub-menu then do something". What we do is add an .expanded class onto the parent list so we get that wider flyout menu effect.

Then everything else follows the same pattern by adding the .active class onto the parent link and displaying the sub-sub-menu. In reverse during a mouseout event the .expanded and .active classes are removed while hiding the sub-sub-menu.

When you see a jQuery selector like $('ul:first',this) it's taking 2 parameters. Normally we only pass one parameter which is the target, but the 2nd parameter is the domain(also known as context). For the mouseover/mouseout event this refers to the sub-menu list item. So within the domain of a list item we want to target the very first child(the sub-sub-menu). Following this same logic we could even build a 4th-tier menu if needed.

Closing

Unlike other navigation with sub-menus this tutorial creates dropdown menus within even measurement. Each flyout menu appears in the same location connected to the parent link by a common color scheme. This may not be an effect that works for every website but it's certainly unique and still provides an exceptional user experience. Feel free to download a copy of my source code and just go nuts with it. I mean don't literally go insane, but yeah the code is free so have fun!

Leave a Reply

Your email address will not be published. Required fields are marked *