Create A WordPress 3.0 jQuery Drop Down Nav Menu
Finally!! A Drop Down WP Nav Menu!
This is what you will be thinking if you're like me and have been searching the web for days on how to use the new wp_nav_menu() to create a nice drop down menu, and finally have full control over how the links are nested and arranged from the dashboard Menus page, and have probably been unable to find much of anything that is helpful in doing so. Am I right? If you know of any other sources please share in the comments.
I know this because I have been searching not just for days, but for months now for any kind of information I could find on making a drop down menu that doesn't use the disgusting way of the past using wp_page_menu(), wp_list_pages(), wp_list_categories(), or any one of the other wp_list_xxx() methods that you were able to do this in the past.
Then this week I found myself in desperate need of a custom wp_nav_menu() that dropped down and was all fancy pants, so I had to suck it up and create it from scratch. This is the WP drop down nav menu I made.

As you can see it is rather big, though I wouldn't consider it a mega menu, just a long list that I found a way to display in not only 4 colums but 2 or 3 columns as well to see which would look best. In the interest of time, I will not make you create 20 menu items for making a menu like this, but it is possible with 4 items, if displaying as 4 columns.
Got Menus?
So first thing we should do is register some menus. This I'll go over quickly since it is more documented and you probably already have it done at least to some extent.
Adding theme support for nav menus has recently changed with an update that was made. You should now be adding support to themes for menus like this.
// Theme support adding changed from 'nav-menus' to just 'menus' add_theme_support( 'menus' );
Once that is done, you need should register a menu or 3 and give it a location for use. I recommend that when you make your menus that you don't go crazy and make a whole bunch, at least not until there is a released fix for the quirk that having more than 4 menu tabs causes. You have to scroll horizontally to view all the tabs for each menu.
Once you have added theme support for menus, you can no register some wp_nav_menus and the location they will be used to give them a context.
// Function for registering wp_nav_menu() in 3 locations
add_action( 'init', 'register_navmenus' );
function register_navmenus() {
register_nav_menus( array(
'Header' => __( 'Header Navigation' ),
'Sidebar' => __( 'Sidebar Navigation' ),
'Footer' => __( 'Footer Navigation' ),
)
);
}
Once your theme supports the use of menus, and registered at least one which you want to use, you then need to open the template file which should display your menu. Using wp_nav_menu(), pass the arguments to it that you need to show different menus and settings.
- The nav menu for will show any menu that is defined for it.
- If one isn't filled out, wp_nav_menu falls back to wp_page_menu
- The menu assiged to the primary position is the one used
- If none is assigned, the menu with the lowest ID is used
Since this is the case, on the Menu page of the dashboard I have created a menu named 'Header'. Then added the following code to the header.php temeplate.
<?php // Using wp_nav_menu() to display menu wp_nav_menu( array( 'menu' => 'Header', // Select the menu to show by Name 'class' => '', 'container' => false, // Remove the navigation container div 'theme_location' => 'Header' ) ); ?>
You can view a list of other arguments here which can be useful depending on your needs.
Now let's check out the HTML code that is output by the wp_nav_menu() function so that you can see what we're working with. I
The HTML Output Of wp_nav_menu()
The structure of the menu that I am going to be building for this tutorial will be able to have custom post types, custom taxonomies, pages, categories and tags, and custom links combined in one menu that I'll be able to reorder simply by dragging and dropping them on the menu page in the dashboard.
Here is what my example menu structure looks like:
The HTML code that this menu structure will output when wp_nav_menu() is called will give me something like this, only with the links and page titles.
<div id="menu-header"> <ul id="menu-main-menu" class="menu"> <li id="menu-item-57" class="menu-item menu-item-type-post_type current_page_item"> <a href="#">No Drop</a> </li> <li id="menu-item-58" class="menu-item menu-item-type-post_type"> <a href="#">Drop Down</a> <ul class="sub-menu"> <li id="menu-item-81" class="menu-item menu-item-type-page"> <a href="#">Link</a> </li> <li id="menu-item-85" class="menu-item menu-item-type-category"> <a href="#">Link</a> </li> <li id="menu-item-82" class="menu-item menu-item-type-taxonomy"> <a href="#">Link</a> </li> <li id="menu-item-83" class="menu-item menu-item-type-tag"> <a href="#">Link</a> </li> </ul> </li> <li id="menu-item-60" class="menu-item menu-item-type-post_type"> <a href="#">Drop Down</a> <ul class="sub-menu"> <li id="menu-item-81" class="menu-item menu-item-type-page"> <a href="#">Link</a> </li> <li id="menu-item-85" class="menu-item menu-item-type-category"> <a href="#">Link</a> </li> <li id="menu-item-82" class="menu-item menu-item-type-taxonomy"> <a href="#">Link</a> </li> <li id="menu-item-83" class="menu-item menu-item-type-tag"> <a href="#">Link</a> </li> </ul> </li> <li id="menu-item-59" class="menu-item menu-item-type-page"> <a href="#">No Drop</a> </li> </ul> </div>
The most important part in this code are the things that can be selected using CSS and jQuery. More specifically, what selectors will select a groups of items. Anything that shows up more than once, can be used to style all that have it.
Which CSS And jQuery Selectors To Use
- div.menu-header
- ul
- li
- a
- menu-main-menu
- menu
- ul.sub-menu
- menu-item
- current_page_item
For now just leave the selectors that are specific to a type alone. The selectors that indicate whether its a post_type, _page, _tag, etc. can be used for selecting a set of those items, but with the menu being easily changeable the set list of items may be altered accidently later on.
So now that we know a little more about what were dealing with, we can style it with some CSS code using these ID and class selectors. You can also enable the CSS Classes option under the Screen Options slide down menu of the dashboard menu page.
Why Won't This Menu Drop Down, Damnit?!
If you are not familiar with making drop down menus you might come to find it frustrating. If you're like me and other people I know, then you try to avoid having to make them at all costs. That is why I've made it simple for you, and have already done the work. Below is the CSS for my drop down menu, which uses CSS3 gradients, border radius and other things.
<style type="text/css">
#menu-header { margin: 0 auto; width: 960px; display:block; }
#menu-header { border-bottom:5px solid #A5C3DE; height:41px; left:0; position:relative; top:30px; z-index:3; }
/***************** SUB MENU - Main Tabs **********************/
#menu-header ul.menu { position:absolute; list-style:none; margin-bottom:0px; width:400px; display:inline-block; }
#menu-header ul.menu li {
background:#deeff7;
margin:0 12px 0 0; padding:0px; width:160px; float:left;
background-image: -moz-linear-gradient(top, #d6e7f7, #deeff7);
background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #d6e7f7),color-stop(1, #deeff7));
border:1px solid #a5c3de;
-moz-border-radius-topleft: 6px;
-moz-border-radius-topright: 6px;
-webkit-border-top-left-radius: 6px;
-webkit-border-top-right-radius: 6px;
}
#menu-header ul.menu li a {
padding:10px 6px; margin:0; display:block; overflow:hidden;
color:#666666; text-shadow:0 1px 0 rgba(255,255,255,.9);
text-align:center; text-decoration:none;
font-size:15px; font-weight:bold;
font-family: Helvetica, Verdana;
}
#menu-header ul.menu li a:hover, ul.menu li a:active {
background:#c6d7ef;
color:#444; text-shadow:0 1px 0 rgba(255,255,255,.7);
background-image: -moz-linear-gradient(top, #a5c3de, #c6d7ef);
background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #a5c3de),color-stop(1, #c6d7ef));
}
/****************** SUB MENU - LEVEL 2 ***********************/
#menu-header .sub-menu {
/* Width of drop menu for changing number of columns:
2 columns: 424px;
3 columns: 638px;
4 columns: 848px;
*/
width: 424px;
background: #c6d7ef;
position:relative;
overflow:hidden;
padding:0px; margin:0px;
}
#menu-header ul.menu li a:hover ul.sub-menu {
background:#c6d7ef;
}
#menu-header ul.sub-menu li {
background:#c6d7ef;
border:1px solid #9cb3c8;
display:block; float:left; margin:-1px; padding:0; width:212px;
-moz-border-radius:0px; border-radius:0px; -webkt-border-radius:0px;
}
#menu-header ul ul.sub-menu li a {
line-height:1.3em; font-size:13px; color:#333; text-shadow:0 1px 0 rgba(255,255,255,.7);
margin:0px; padding:10px 5px; text-align:center;
}
#menu-header ul ul.sub-menu a:hover {
color:#345; text-shadow:0 1px 0 rgba(255,255,255,.9);
background-image: -moz-linear-gradient(top, #d6e7f7, #deeff7);
background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, #d6e7f7),color-stop(1, #deeff7));
}
#menu-header ul ul {
display: none; /* For testing, change to display: block; */
list-style:none;
z-index:100;
}
#menu-header ul li:hover > ul {
/* Uncomment to show drop down for testing purposes
display: block;
*/
}
</style>
There are a few comments in this code that you should notice. First, you can control the width of the drop menu and the number of columns the list items form using the width amounts I've outlined here.
/* Width of drop menu for changing number of columns: 2 columns: 424px; 3 columns: 638px; 4 columns: 848px; */
The other part that is very important and one of the single things you should get from this tutorial is below. The trick to making drop menus is to make the parent item of the child items visible using display: block;. That way you can position it correctly and design the desired look and feel while it is visible without hovering. Once that's done you can hide it with display: none;.
#menu-header ul ul {
display: none; /* For testing, change to display: block; to make visible */
list-style:none;
z-index:100;
}
#menu-header ul li:hover > ul {
/* Uncomment to show drop down for testing purposes
display: block;
*/
}
Animating The Drop Menu With jQuery
This is the jQuery code that I wrote for making my drop down menu a little more slick. It's a basic animation that simply slides up and down when hovering on and off of the tabs and drop menu.
<script type="text/javascript">
$(function() {
$("#menu-header ul.menu ul").css({ display: 'none' });
$("#menu-header ul.menu li").hover(function() {
$(this).find('ul.sub-menu')
.stop(true, true).delay(50).animate({ "height": "show", "opacity": "show" }, 200 );
}, function(){
$(this).find('ul.sub-menu')
.stop(true, true).delay(50).animate({ "height": "hide", "opacity": "hide" }, 200 );
});
});
</script>
There is a .delay() that prevents the animation from firing immediately when your mouse touch the tab buttons. Without the .delay() whenever you move your mouse over the tabs, but not intending to open the menu, it would cause it to flicker from your moving too fast for it to drop. I've made it so you have to stop on the tab for it to drop. Just thought I'd explain that since it was something I learned the hard way doing this. That's pretty much all there is to it.
Check This Out On WPHonors
You can see another example of this drop menu as a single column drop down over on WPHonors.com. The menu I made for that site is much nicer looking because I used much more CSS3 styling and customizing.
Also, I wrote this post a long time ago, and realized I never published it. So don't kill me if it turns out to be incomplete or doesn't work. If you have any questions you're always welcome to post a comment below.









User Comments
( ADD YOURS )lettre October 25
great tuto, thank's :)
Garth October 28
Jared,
Thanks for the tutorial. I've got the menu recognized, but the sub-menu is displaying without a hover and it's not aligned correctly. Is that a matter of CSS?
http://www.mealtrader.com/simplotgames/
Notice the "history" menu item is under the Meet Information menu when it's suppose to be under the About menu item only after the hover. Any thoughts?
Garth recently posted..American Hospitals Receive Low Patient Satisfaction HCAHPS Scores
Jared October 29
It would appear to be a CSS issue yes. But, is the History menu item on the same level as the About item? Or is the History one supposed to be a sub-item of About? It looks like you have them as on the same level, and the History one is just wrapping to the next line since there's not enough room next to About for it to fit? Maybe just my small screen though.
Travis November 4
Where does the jquery code go? Does it go in the style.css file or header.php file? If neither, where?
Thanks
Jared November 4
You can put it in either header or footer file. I would put it in the footer.php personally. Just make sure you include the jquery.js source before your jQuery code or it won't work.
Baihaqi November 6
Hi,
Just wanted to ask you about the custom menu.
I use the custom menu for the main navigation of the website.
Currently I have 10 menu items (including sub-menu) and I notice that after having this 10 menu items, I cannot add any other sub menu. Well, I can add, but when I click update, the wordpress won't save it. Is this any limitation on how many menu items allowed?
Baihaqi recently posted..Polytopes
Jared November 7
I've never heard of there being a limit. I haven't tried to have more than 10 top level items before, but I have made a mega menu that had about 20 sub items under a top level menu item, and that worked just fine.
Albert December 4
Seems It is good tutorial. I want to make single drop down menu for Categories at my blog http://sarugu.com.
Let me try this. Hope it will work out.
Albert recently posted..HostGator Black Friday offer at Indian Standard Time
Horhe January 13
Great text. However, it seems i'm doing something wrong?
It's displayed as a simple dropdown, without any effect. As if it's not recognizing or accepting javascript.
Also, why are you declaring menu-header with #, and its a class? Maybe it sound stupid, but shouldn't it be .menu-header?
Jared January 14
You are right, it should be #menu-header in the html. Since there is only going to be one header menu. That may be what's causing it to not show the effect. Try changing that if you haven't.
I'll fix it in the tutorial.
lucky_girl February 18
Great post. You seem to have a good understanding that how to create a professional drop down menu. When I entering your blog, I felt this. Come on and keep writing your blog will be more attractive. To Your Success!
tpok April 16
Got any advice on how to make a third level. I'm making it a single column with more than 1 level. I'm feeling a bit Newb.
Julie June 17
Great Script! Thanks for sharing. I am having a problem with the drop down only showing in Chrome, not IE or Firefox. Was wondering if you could help me.
sivakumar June 23
Thanks for your post, i will frequently check this site.
chat July 11
jquery is really powerfull to do this
Steve July 21
It looks like you have them as on the same level, and the History one is just wrapping to the next line since there's not enough room next to About for it to fit. Thank you for the idea.
Trackbacks