Make your own WordPress drop down menu
When it comes to creating a site that has multi-level navigation, a drop down menu is often your best means of keeping the navigation simple and uncluttered. There are a few plugins that you can use to achieve this, but I’ve found that many of them make too many assumptions and don’t work exactly how I’d like them too. For that reason, I’ll detail a simple means of making your own WordPress drop down menu.
Here’s a demo of what we’re going to accomplish. (Tested in IE7 & FF)
Getting started
Firstly, you’ll need to setup your pages in WordPress in a hierarchal manner. IE:
- Home Page
- About Us (2)
- What We Do
- What We’ve Done
- Who Works For Us
- Services (6)
- Portfolio
- Our Clients
- Contact Us
… for example. NOTE: The numbers in brackets represent the ID of that page. Replace this later with your own actual page ID’s.
This will usually generate nested <ul> and <li> list that will work as your navigation.
<ul id="nav"> <li><a href= "#">Home Page</a></li> <li><a href= "#">About Us</a> <ul id="aboutus"> <li><a href= "#">What We Do</a></li> <li><a href= "#">What We've Done</a></li> <li><a href= "#">Who Works For Us</a></li> </ul> </li> <li><a href= "#">Services</a> <ul id="services"> <li><a href= "#">Portfolio</a></li> <li><a href= "#">Our Clients</a></li> </ul> </li> <li><a href= "#">Contact Us</a></li> </ul>
Sorted?
Making it dynamic
What you’re going to do now, is break that list down somewhat and create your own navigation. The top level menu items will be static, and their subpages will be dynamic. Like so:
<ul id="nav"> <li><a href= "#">Home Page</a></li> <li><a href= "#">About Us</a> <ul id="aboutus"> <? wp_list_pages('title_li=&sort_column=menu_order&child_of=2'); ?> </ul> </li> <li><a href= "#">Services</a> <ul id="services"> <? wp_list_pages('title_li=&sort_column=menu_order&child_of=6'); ?> </ul> </li> <li><a href= "#">Contact Us</a></li> </ul>
The Script
There’s a tiny piece of javascript required to show/hide the drop down menu’s. From an accessibility point of view, you can link the top level navigation item so that if JS is disabled, the user will still be able to get around your site. Here’s the script.
// JavaScript Document function toggleLayer(whichLayer) { if (document.getElementById) { // this is the way the standards work var style2 = document.getElementById(whichLayer).style; style2.display = style2.display? "":"block"; } else if (document.all) { // this is the way old msie versions work var style2 = document.all[whichLayer].style; style2.display = style2.display? "":"block"; } else if (document.layers) { // this is the way nn4 works var style2 = document.layers[whichLayer].style; style2.display = style2.display? "":"block"; } }
Your complete navigation would look as follows (including the Javascript commands):
<ul id="nav"> <li><a href= "#">Home Page</a></li> <li onmouseover="javascript:toggleLayer('aboutus');" onmouseout="javascript:toggleLayer('aboutus');"><a href= "#">About Us</a> <ul id="aboutus"> <? wp_list_pages('title_li=&sort_column=menu_order&child_of=2'); ?> </ul> </li> <li onmouseover="javascript:toggleLayer('services');" onmouseout="javascript:toggleLayer('services');"><a href= "#">Services</a> <ul id="services"> <? wp_list_pages('title_li=&sort_column=menu_order&child_of=6'); ?> </ul> </li> <li><a href= "#">Contact Us</a></li> </ul>
The CSS
Now, you’ll need to do a bit of freestyling on your CSS to style it as you’d like and getting it positioned as it should be. The important thing to include, is the CSS to hide the nested <ul> and the absolute positioning so that it doesn’t affect any other elements when its shown:
@charset "utf-8"; /* CSS Document */ * {margin:0;padding:0;} body {text-align:left;padding: 30px;font: 12px Tahoma, Arial, Helvetica, sans-serif;} ul, ol {padding: 10px 0;} #nav ul {display:none;position:absolute;margin: 16px 0 0 -1px;} /* hide the sub nav */ *+ html #nav ul {margin: 16px 0 0 -122px;} /* ie 7 hack */ #nav li {list-style:none;display:block;float:left;} #nav a {display:block;float:left;padding: 5px 15px;border:1px solid #ddd;margin: 0 0 0 -1px;text-decoration:none;width:90px;} /*subnav styling*/ #nav ul li, #nav ul li a {float:none;} #nav ul li a {margin: -1px 0 0 0;width:150px;} #nav ul li a:hover {background:#efefef;color:#000;}
This is the CSS used to achieve the effect in the demo. You can of course change it to suit your site’s styles.
And presto, you’ll have a drop down menu. As you add sub pages in your WP admin, those pages will automatically be included in your drop down.
Slick
nomad-one
great stuff WP Guru, I’ve got a drop down on my wordpress site currently but only realised recently it doesn’t work in certain earlier versions of IE, which sucks, so many of my subcategory pages are not accessible.
How backward compatible is this particular solution?
MarkB
as long as JS is enabled on the browser, its just a matter of setting your CSS correctly for each browser so the menu drops down where it should.
of course, by adding a URL to the top level navigation item, you can maintain your accessibility levels for those without JS.
nomad-one
Just retracing my steps through this tut and was wondering whether you have a simple solution to making drop down links which only act as top level links and don’t actually go anywhere.
Eg, the link does not link to a page but only allows you to place subpages inside of it.
MarkB
You mean a dropdown that generates a category list, but the top level categories are ‘optgroup’ html elements?
Mark
Is there a way to make the top level menu items dynamic as well? So that everything is dynamically generated by Wordpress, so if you were to make a new page and make 4 subpages for it, the parent page and its subpages appear in a dropdown menu automatically. Is this possible?
MarkB
Hey Mark. Because the parent LI elements have ID’s and are given that onmouseover command, it’d be tricky to use the WP wp_list_pages command to generate the page list automatically. I’m sure someone with a bit more JS knowledge could create a tweaked command that says the LI’s under this UL must dropdown here, etc…
but this particular script cant do the top-level items as dynamic, no…
Mark
Ah, oh well.
Thanks for the quick reply!
Valon
This sounds great as I have tried various drop-downs. Is there
Valon
This sounds great as I have tried various drop-downs. However, I must be doing something wrong, as I can’t get the menu to work properly.
I’m thinking the trick is in this part: javascript:toggleLayer(‘aboutus’) ?!
The rest I’ve followed as you had described.
Chris
Bloody hell! This is great stuff and works like a charm… but how on earth do I highlight page parents and children.. or anything at all when on current page? I’ve been trying for days with no luck at all. Please please pretty please… help me before I go mad!
My menu looks like this:
<a href= “”>
Chris
Um… nevermind how my menu looks like … but an example on the demo menu would be great
Pedro
I’m sorry, but where do I put the Javascript code?
gnfoster
Yeah, it looks great, just what I’m trying to do. But where do these files go? Script… Css… etc…
Thanks!!!
gnfoster
Maybe someone out there can turn it into a plugin? There really aren’t ANY that I’ve found that work well. Especially with the newer 2.6+ Wordpress
Dante
How can you integrate ProjectSeven.com Menu Systems into a WordPress theme layout? Does anyone know how to do this?
Sarah
Anyway to get this to work in IE6? The drop downs show up underneath the next button instead of directly below…
shammi
this is my first menu
<li class=”current_page_item” ><a href=”/”>Home
this is the next menu
so how do i modify it now. how do i seperate the child pages form the parent.
Dwaynne
I have the same issues as Sarah and Chris:
1. How do I highlight the current item in the main navigation?
2. How do I get it to work in IE6????
Any help appreciated!
Chris
I haven’t tried this yet but I think u can make it work by adding and styling .current_page_parent in your stylesheet. wp_list_pages autogenerates this class on parent pages if I remember correctly.
Dwaynne
i’ll try it..thanks! I am tryign to get the menu working here: http://www.cipore.org.
The IE6/7 issue is my bigger worry, though. Any thoughts on that one??
Dwaynne
Hullo? : ) IE fixes?
Joe
What do I name the .JS file?
beginner
I believe you can name js file to whatever you like, and just make sure to load your js file in the header meta as blow:
<script type=”text/javascript” src=”/wp-content/themes/gloriousfuture/nav.js”>
Scott
I am having trouble with this in the Chrome browser.
Monni
I am familiar with editing my themes CSS but where do i edit the navigation script? What file?
Monni
I believe you can name js file to whatever you like, and just make sure to load your js file in the header meta as blow:
in the header meta? of the CSS? of some other file which is?
Monni
Do i put the JS to my WP-includes/JS/ ?
raj
Good work, its really simple for beginners like me, i had tried it out and worked well for me.
ivy
thank you very much for posting this…it worked for me too..:)
zach
Is there a way to get the entire menu automatic (including the Parent Pages?)
neall
do you do like a ” der ! ” explanation of all this ?
der = haven’t a clue > requires step1, step2,
WillM
I’ve followed this, and the menu’s up, but the dropdown menu doesn’t work. Either wp_list_pages isn’t working for me, or the javascript isn’t. Any suggestions? I’m using WP 2.5.
Thanks!
Will M
mandy
i added the script to my header.php file and the css to my stylesheet, but the menu is not dropping down and de css only messes up my whole site layout. i dont understand a thing of this. please help?
master nik
thanx for help
erikh
Like WillM I followed this and the menu is up, but the dropdown doesn’t work. I think the wp_list_pages is working though because if I get rid of the display:block; in the ul code I can see the subnavigation appear.
But for some reason when I hover over the menu it isn’t working. Any Ideas?
I’m working locally with MAMP.
Norm
Fine if you don’t have IE6 users. Useless otherwise.