What we'll be working with
We'll be using the jQuery hover event to accomplish this effect. If you want a more detailed explanation of how it works, read that part of my sliding highlight tutorial (it's about two-thirds of the way down).
Let's get started!
HTML
Let's start with our HTML structure. This is a bit more HTML than previous examples, but not really much more complicated. Copy this into the BODY tag of your HTML file:
<div class="menu">Let's break this down.
<div class="navlink">
<a href="#">Link 1</a>
</div>
<div class="navlink">
<a href="#">Link 2</a>
<div class="dropdown">
<a href="#">Link 2.1</a>
<a href="#">Link 2.2</a>
<a href="#">Link 2.3</a>
</div>
</div>
<div class="navlink">
<a href="#">Link 3</a>
<div class="dropdown">
<a href="#">Link 3.1</a>
<a href="#">Link 3.2</a>
</div>
</div>
</div>
- The DIV with the class "menu" is the overall container, and will be the menu bar.
- The DIVs with the class "navlink" are contain the links that will appear in the main menu bar, as well as their associated drop-down menus.
- The DIVs with the class "dropdown" are the drop-down menus that will show up when we hover over the top-level links in the menu bar.
Here's the style rules for this menu. Copy this into the HEAD tag of your HTML document:
<style type="text/css">A lot of the CSS above is purely for appearance and doesn't relate directly to the drop-down functionality. I am only going to go into detail on the rules and properties that are relevant to the drop-down menus. If you want to learn about the rest, click the property name you're interested in in the code above.
.menu {
background: gray;
}
.menu a {
color: white;
text-decoration: none;
}
.navlink {
display: inline;
position: relative;
}
.navlink a {
padding: 5px;
}
.dropdown {
display: none;
position: absolute;
top: 100%;
left: 0;
background: lightgray;
}
.dropdown a {
display: block;
color: gray;
white-space: nowrap;
}
</style>
.navlink
- position: Setting the position to "relative" allows child elements of the "navlink" DIVs to use their position and dimensions as a reference for absolute positioning. This means we can make the drop-down menus appear underneath the correct link in the menu bar.
.dropdown
- display: Setting display to "none" makes the "dropdown" DIVs to be hidden by default. We will use jQuery to reveal them.
- position: Setting the position to "absolute" lets us position the DIV based on the position and dimensions of its parent container.
- top: The "100%" refers to the height of the parent element, in this case the "navlink" DIV containing each "dropdown" DIV. The top of the "dropdown" DIV will be positioned the full height of the "navlink" DIV from the top of the "navlink" DIV, meaning it will be aligned with the bottom of the "navlink" DIV. If we set this to "50%", the top of the "dropdown" DIV would be positioned half-way down the "navlink" DIV, in the middle of the menu bar.
- left: This just aligns the left edge of the "dropdown" DIV with the left edge of the "navlink" DIV.
Now to the interesting part. Here's the scripts to copy into the HEAD tag of your HTML document:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>The first SCRIPT tag just adds the jQuery library to your page so you can use jQuery. The second one contains our actual functionality.
<script type="text/javascript">
$(document).ready(function () {
$(".navlink").hover(
function () {
$(this).children(".dropdown").delay(250);
$(this).children(".dropdown").slideDown();
},
function () {
$(this).children(".dropdown").slideUp(
'normal',
function () {$(this).clearQueue();}
);
}
);
});
</script>
As I explained in my sliding highlight tutorial, the hover event calls one function when the mouse moves over the selected element, and a second function when the mouse moves off. Please note that the jQuery selector is triggered by hovering over the "navlink" container, not the link in the menu bar. If the event were attached to the link showing in the menu bar, the drop-down menu would disappear when you moved your mouse down to click a link inside the drop-down area, because you would have moved your mouse off of the link in the menu bar. By attaching the event to the "navlink" DIV, which contains both the menu bar link and the drop-down menu, the drop-down will not disappear until you mouse-off both the menu bar link and the drop-down menu.
Both the mouse-over and mouse-off functions use the code '$(this).children(".dropdown")'. The first part simply refers to the current element, which is the "navlink" DIV that triggered the hover event. The "children" bit causes the code to find any elements inside the current element that have the class "dropdown" and apply the animation to them.
The "slideDown" and "slideUp" effects come built-in to jQuery, so you don't need to worry about how they work. The "delay" function just causes the script to pause for a quarter second (250 milliseconds) before making the menu drop down. This isn't strictly necessary, and is mostly there for smoothness of operation.
The important part of this script is in the mouse-off function, the second one. This script causes the drop-down menu to slide back up out of sight. The word 'normal' refers to the speed of the animation, and the next line is what's called a "callback function". This is basically a function that gets executed after the slide-up animation has finished. In this case, it clears the animation queue of the "dropdown" DIV that has just slid up and out of sight. Without this, you can have some very weird effects with your menus. With this line not included, I rapidly moused-over and moused-off the menu several times, causing it to bounce up and down even after I had moved my mouse away. Each mouse-over and mouse-off event added another animation to the queue, resulting in the weird bouncing effect. Adding the "clearQueue" callback function ensures that after the menu has slid back up, it won't slide down again until you deliberately hover over the menu bar link again.
That's about it! If you have any trouble with the tutorial, want clarification on anything, or have suggestions for future tutorials, let me know in the comments!
Aaron, this is so interesting! I wish I had more time to investigate all this more thoroughly and try it out on my own. Also, I think you lay everything out there really clearly and concisely, so good job!
ReplyDeleteGreat post, Aaron, and great information. Your comment about hovering on the navlink helped me to understand how to fix that problem of keeping the drop-down menu "dropped down." Also, good explanation of the "callback function" and how that works.
ReplyDelete