This article will demonstrate how to create an animated rollover drop down menu using HTML, CSS, and jQuery. Take a look at the demo to see the final result, or download the files directly.
Tested on
PC: IE6-8, Firefox; Mac: Safari, Firefox, Opera
HTML Structure
-
-
<ul id="nav1" class="menu_body">
-
<li class="menu_head"><a href="#">Nav Header 1
</a></li>
-
<li><a href="#">Nav Item 1
</a></li>
-
<li><a href="#">Nav Item 2
</a></li>
-
<li><a href="#">Nav Item 3
</a></li>
-
<li><a href="#">Nav Item 4
</a></li>
-
<li><a href="#">Nav Item 5
</a></li>
-
<li><a href="#">Nav Item 6
</a></li>
-
</ul>
-
… nav2 …
-
… nav3 …
-
… etc …
-
</div>
Each navigation menu is a list that sits inside a div with the ID nav. Give the list a class of menu_body and an id of nav1 for the first one, nav2 for the second, and so on. The naming here is important not only for the styles, but because the jQuery functions look for the “nav#” items. Also, give the first list item the class of menu_head. This is the item that will remain when the navigation is collapsed. Giving it a class will allow you to style it differently if necessary.
Styles
-
/* Nav */
-
-
#nav {
-
float: left;
-
width: 480px;
-
height: 21px;
-
display: inline;
-
margin: 10px;
-
}
-
#nav ul {
-
float: left;
-
width: 160px;
-
margin: 0;
-
padding: 0;
-
overflow: hidden;
-
list-style-type: none;
-
visibility: hidden;
-
background: #00a95c;
-
}
-
#nav li {
-
float: left;
-
}
-
#nav a {
-
float: left;
-
width: 160px;
-
color: #fff;
-
text-decoration: none;
-
display: block;
-
margin: 0;
-
padding: 8px 0 8px 20px;
-
font-size: 14px;
-
}
-
#nav ul a:hover {
-
font-weight: bold;
-
background: url(subnav_arrow1.gif) 10px 50% no-repeat;
-
}
-
-
#nav li.menu_head a {
-
padding: 2px 0 0 6px;
-
padding-bottom: 10px;
-
}
-
#nav li.menu_head a:hover {
-
background: none;
-
}
The styles is what you’ll want to start customizing for your needs. You’ll want to update the #nav with the width and height of your navigation bar. This is the container for the whole navigation so you can change margins or positioning as needed.
Next you’ll want to update the width in the #nav ul section. This is the width of the nav item in the menu as well as the drop down. You’ll probably want to change the background color too. You’ll notice that the visibility is set to hidden. The reason why will be explained in the jQuery section.
Setting #nav li to float left fixes a bug in IE6 that adds extra spacing between each list item.
Again, change the width in #nav a to the same as the width you changed in #nav ul. Adjust color, padding, etc as needed.
#nav ul a:hover adds the rollovers effects to the each navigation link, and #nav li.menu_head a and #nav li.menu_head a:hover override those styles so you can change the behavior of the first navigation item.
jQuery Functions
-
$(document).ready(function () {
-
-
var startingHeight = 21; // Specifies the height of your navigation when collapsed
-
var speed = 300; // Specifies the speed of the animation
-
-
var heights = new Array();
-
-
var i = 1;
-
while ($("#nav"+i).length) {
-
heights.push($("#nav"+i).height() + 8);
-
$("#nav"+i).height(startingHeight);
-
$("#nav"+i).mouseover(function () {
-
$(this).stop().animate({height:heights[this.id.substr(3)-1]},{queue:false, duration:speed});
-
});
-
$("#nav"+i).mouseout(function () {
-
$(this).stop().animate({height:startingHeight+‘px’}, {queue:false, duration:speed});
-
});
-
i++;
-
}
-
-
$("#nav ul").css("visibility", "visible");
-
-
});
You should only need to modify 2 variables in this file unless you want to customize the functionality. startingHeight should equal the height of your #nav div. This is the height that the mouseovers will return to on mouseout. The speed controls how fast the animation runs and can either be one of the jQuery standard strings “slow,” “normal,” or “fast” or a number in milliseconds.
When I initially created this I came across a problem where the lists would have slightly different heights in different browsers. However, since I am animating the heights I needed to know those specific values. I initially tried solving this this by having the navigation start fully open, grabbing the heights of each list and setting the heights back to the value for the collapsed nav. This worked, however there was sometimes a flicker when the page first loaded. Especially if the load time was longer on a slower connection. The solution to this was to set the style of the lists to visibility: hidden which hides the navigation from view but unlike display: none keeps the space that the item take up. So I could grab those heights (the “+8” adds 8 extra pixels to the bottom for extra padding) without anybody seeing the list, reset the heights to collapsed, and once that is finished turn the visibility back on. That’s what the first two lines in the loop do. They add the current height to an array.
The loop starts at the id nav1 and loops through and increments until it finds one that doesn’t exist. It’s important to start the nav’s at 1 and keep them consecutive. The .length attribute returns 0 if an item does not exist ending the loop.
The next section in the loop applies the mouseover and mouseout functions. This applies a stop and and animate function. If you remove the stop and the queue attributes and then test the rollovers a few times you’ll see why. By default jQuery queues animation. The stop in combination with the queue: false prevents this from happening.
The height that it’s using is grabbed from the array by pulling out the number from the “nav#” id. This was the best way I could think of doing it, because I couldn’t figure out how to pass the dynamic variable “i” into the mouseover. If there’s a way to do this let me know in the comments. The mouseout simply returns the list to the original height.
Finally after all of this is set up, the visibility is turned back on. Let us know in the comments if you use this for your website.
Tips:
- Style each menu differently by targeting them with
#nav1 etc. in the CSS.
- Replace the text in the
menu_head with an image for a graphical navigation.