Easily create WordPress 3.x hover/rollover menus with Jquery.

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:

[html]
<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>
[/html]

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:

[css]
.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; }
[/css]

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:

[js]
<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>
[/js]

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.