Ever since the release of WordPress 3.0 a couple months ago, people have been moving quickly to implement one of it’s most useful new features, the Custom Navigation Menus. They are easy to create, even easier to manage and generally help stop developers from constantly coming up with different and disperate solutions to this very common problem.
There are plenty of articles on how to set up and use Custom Navigation Menus, but we are going to focus here on how to easily style and apply some javascript (jquery) code to make them into fancy hover menus with the submenus being revealed on rollover. Moreover, this code utilizes a timeout, so that the menus don’t “flicker” as users enter and leave the submenus. This is required for a cleaner user interface.
First, the custom menus create html that looks like this:
<div class="menu-top-nav-container"><ul id="menu-top-nav" class="menu"> <li id="menu-item-145" class="menu-item menu-item-type-custom current-menu-item current_page_item menu-item-home menu-item-145"><a href="/">Home</a></li> <li id="menu-item-129" class="menu-item menu-item-type-post_type menu-item-129"><a href="/about/">About</a> <ul class="sub-menu"> <li id="menu-item-242" class="menu-item menu-item-type-post_type menu-item-242"><a href="/about/page1">Page 1</a></li> <li id="menu-item-124" class="menu-item menu-item-type-post_type menu-item-124"><a href="/about/page2/">Page 2</a></li> </ul> </li> </ul> </div>
I’m using a very simple example here, where there are 2 toplevel pages (home and about), and about has 2 subpages. You can style this menubar any way you would like, but the standard method of having the links appear directly below in a horizontal row, would look something like this:
.menu-top-nav-container { clear: both; min-height: <match your total height here>px; }
.menu-item a { margin-left: 20px;}
.menu-item a:link { text-decoration: none; }
.menu-item a:hover { text-decoration:none;}
.menu ul { margin: 0; padding: 0 list-style-type: none; }
.menu li { display: inline; position: relative;}
.sub-menu { list-style-type:none; display: none; position: absolute; width: <container size>px; height: <submenu height>px; }
We are assuming you have named your menu “top-nav”, but you can change to suit. This will match all the standard styles that the menuing system will put into your site once you enable the menu and add it to the template.
The last part of this mini project is to add some jquery code to your js library or in the header:
<script type="text/javascript">
var $j = jQuery.noConflict();
$j(document).ready(function(){
var timer;
$j('#menu-top-nav li').hover(
function() {
if(timer){
clearTimeout(timer);
timer = null;
}
$j(this).children('.sub-menu').fadeIn();
},
function() {
timer = setTimeout(function(){
$j('.sub-menu').fadeOut();
}, 1000);
}
);
});
</script>
This code will traverse all submenu children of the parent and display them using the .hover() function in jquery. But we also set a timer to 1000ms (1 second), and leave the menu up when the user scrolls off, so that it will not flicker on and off as they go between the menu item and the submenu, or when they accidentally scroll off the submenu prematurely.
For SEO, it is also possible to remove the display:none from the css submenu entry, and add a $j(‘.sub-menu’).hide() as the first line of your javascript, but if you have a very complex page, you may have a flickering of the submenus on load as the dom loads the HTML, then the javascript hides the submenus. It’s not worth it to me, but may suit some folk.
That’s all there is to it. Happy Blogging.


Thanks for the info bro, this is great. However, I wanted to know what would be the difference (in terms of styling) if I wanted my sub-menu items to appear as a vertical row when hovering over the parent list item.
Thanks again,
-Benjamin
Benjamin, try something like this in your stylesheet, adjust to taste. This should give you the more standard, simple dropdown menu.
.menu ul { margin: 0; padding: 0; list-style-type: none; } .menu li { display: inline-block; position: relative; margin: 0 10px; height:24px; } .sub-menu { list-style-type:none; display: none; position: absolute; width: 200px; background: #000000; border: solid 1px #be3e18; opacity:.75; filter:alpha(opacity=75); filter: alpha(opacity=75); } .sub-menu li { margin: 0;}And here’s a new (easier) chunk of jquery to use in your simpler case:
$j("#menu-top-nav li").hover(function(){ $j(this).addClass("hover"); $j(this).children('.sub-menu').fadeIn(); }, function(){ $j(this).removeClass("hover"); $j(this).children('.sub-menu').fadeOut(); });Awesome little jquery implementation there, I’m ashamed to admit it took me longer than I would have thought possible to get it working on my site–always close your parenthesis (my mistake not yours(obviously).
I couldn’t resist.
Anyway thanks.
Hi Michael
thanks for the code!!you’ve stopped my seemingly unending search in its tracks! it works great! however is there a way that i can make the parent link ‘unclickable’- i could create an extra page if necessary, but this then defeats the purpose of the rollover really.
again, thanks as this has been extremely helpful!
The only way I know how to do this (and I just did it a week ago for a client!) is to do this is to go into your Admin -> Appearance -> Menu, then select the top “Screen Options” button, and make sure that “CSS Classes” is clicked. Now your menu items are going to have more options, specifically the ability to add a class to them. On the one that you don’t want a link with, add the class “nolink”. You can now make a “custom link” instead of a page, and just put a # as the href.
Now, we’ll need a bit of javascript (particularly jquery here), which you can add to your existing jquery code (right after your document ready call is fine):
$j('.nolink > a').removeAttr('href');
That will remove the ability to click on any menu item that has the class “nolink”. If anyone else has an easier (Built into WP way) to do this w/out having to add Javascript, please let me know!
Worked a treat! very much appreciated-it couldn’t have been simpler and thats coming from someone with very limited knowledge of code, especially java!thanks again!
Thanks for the compliment DBH. Glad it worked for you. We also do contract work for designers to help you out if you get over your head with code of any sort.