Displaying WordPress categories in a horizontal dropdown menu.
Posted on Wednesday the 16th of January, 2008 at 2:05 pm in Asides, WordPressOne of my readers recently asked how I created my horizontal menu bar: the short answer is by mixing CSS and Javascript.
The first step is to get WordPress to display the menu as a hierarchical list without a title. <?php wp_list_categories('sort_column=name&sort_order=asc&style=list&children=true&hierarchical=true&title_li=0'); ?>
We then wrap this WordPress code in the following so we can style it.
<div style="text-align:center;"><ul id="menu" style="padding:0; margin:0;"><?php wp_list_categories('sort_column=name&sort_order=asc&style=list&children=true&hierarchical=true&title_li=0'); ?></ul></div>
I added this to my header.php, but you can add it anywhere you want it to appear.
The CSS is fairly simple and you just need to add it to your theme’s style.css file.
ul#menu {margin: 0;padding: 0;list-style: none;width: 100%;font-size:1.2em;}ul#menu li {float: left;padding: 0;margin: 0;border-right:solid 1px #fff;}ul#menu ul li {float: none;position: relative;border-bottom: 1px solid #7EAED7; /* fixes gap problem in IE */border-left: 1px solid #FFF;z-index:1000;}ul#menu li ul {margin: 0;padding: 0;display:none;list-style: none;position: absolute;background: #9CC;}ul#menu ul ul{margin-left: .2em;position: absolute;top: 0; /* if using borders, -1px to align top borders */left: 100%;}ul#menu * a:hover, ul#menu li a:active{background:#7EAED7 !important;color: #FFFFFF;}ul#menu li a:link,ul#menu li a:visited,ul#menu li a:hover,ul#menu li a:active{display: block;padding: .2em .3em;text-decoration: none;background: #5587B3;color: #FFFFFF;}ul#menu ul li a:link,ul#menu ul li a:visited,ul#menu ul li a:hover,ul#menu ul li a:active {width: 8em;}- Use the following to copy and paste the code.
Of course you will need to change the colors and text sizes to ensure it blends with the rest of the theme.
Now the last step is the to make it work as a drop-down list on all browsers. This could be done in Firefox with a simple CSS declaration, but Internet Explorer doesn’t understand the :hover pseudo classes, so we mimic this in Javascript.
<script type="text/javascript">/*<![CDATA[*/var mbA,mbT,mbTf,mbSf;var mbR = [];function mbSet(m) {if (document.getElementById&&document.createElement) {var m=document.getElementById(m);mbR[mbR.length] = m;var i;e=m.getElementsByTagName('a');if (!mbTf) mbTf=new Function('mbHT();');if (!mbSf) mbSf=new Function('mbS(this);');for (i=0;i<e.length;i++) {e[i].onmouseout=e[i].onblur=mbTf;e[i].onmouseover=e[i].onfocus=mbSf;}m=m.getElementsByTagName('ul');for (i=0;i<m.length;i++) {mbH(mbL(m[i]));}}}function mbHA() {if (mbA) {while (mbA) mbH(mbA);mbHE('block');}}function mbHT() {if (!mbT) mbT=setTimeout('mbHA();', 0);}function mbTC() {if (mbT) {clearTimeout(mbT);mbT=null;}}function mbS(m) {mbTC();if (mbA) while (mbA&&m!=mbA&&mbP(m)!=mbA) mbH(mbA);else mbHE('none');if (mbM(m)) {mbSH(m,'block');mbA=m;}}function mbH(m) {if (m==mbA) mbA=mbP(m);mbSH(m,'none');mbT=null;}function mbL(m) {while (m && m.tagName != 'A') m = m.previousSibling;return m;}function mbM(l) {while (l && l.tagName != 'UL') l = l.nextSibling;return l;}function mbP(m) {var p = m.parentNode.parentNode;if (p.tagName == 'UL') {var i = 0;while (i <mbR.length) {if (mbR[i] == p) return null;i++;}} else {return null;}return mbL(p);}function mbSH(m,v) {m.className=v;mbM(m).style.display=v;}function mbHE(v) {mbHEV(v,document.getElementsByTagName('select'));}function mbHEV(v,e) {for (var i=0;i<e.length;i++) e[i].style.display=v;}/*]]>*/</script>- Use the following to copy and paste the code.
A couple notes on the previous code.
- To activate it, change your theme’s <body> tag to <body onload=”mbSet(’menu’);>
- It was not written by me, but I’ve been using it for a long time and don’t remember where I got it.
- It can occasionally create a JavaScript error, and I’ve intended to rewrite it for a long time, but it usually works fine.


Thanks a Zillion, Aaron!
I’ll give it a whirl.
Regards,
S.K
Reply to S.KYou’re welcome.
Reply to AaronPlease I just don’t understand where in the wordpress files should I put the javascript that enables I.E to read the roll over..
Do I make a file apart or should I insert it in the index.php or something ?
Thanks for your reply
Reply to CecileCecile
You insert into your header.php file before </head>.
Reply to AaronHi Aaron!
great work
can I use this method also to create a hor. menu of my pages???
What should I change in the codes?
thanks, Fre
Reply to freriekeIf you want to use this method with pages, you should be able to basically change wp_list_categories to wp_list_pages.
Reply to AaronI am trying to use this on pages instead of posts, but am unable to get the subpages to drop down.
Reply to AdamI did change from wp_list_categories to wp_list_pages.
here is my string <?php wp_list_pages('sort_column=post_title&sort_order=asc&style=list&children=true&hierarchical=true&title_li=0'); ?>
I love the dropdown menu, however, it seems like the subcategories like to magically disappear when moused over. This happens on both my website and yours. Any suggestions to prevent this behavior? It almost seems like the problem is less apparent when using a smaller browser window, but that might not be the case. It does this both in Firefox and Safari (haven’t tested IE yet), and it is present in both though it doesn’t seem to happen as much in Safari.
Also, just want to clear up where you mention changing the tag; it is missing a quote after the ending parenthesis which breaks the function. As a warning to others, if you copy and paste it, be sure to replace the weird angled single-quote things with a standard single quote. I missed this and it took me forever to catch (fortunately Firefox’s error console pointed it out).
Reply to DylanTHANK YOU! I just spent 20 minutes trying to figure out what was wrong. Everything worked fine except the drop downs.
In case anyone isn’t clear how to fix it, add a double quote to the end after the last parenthesis, retype the first double quote so it’s correctly formatted and retype the single quotes around menu.
Reply to caseyAny chance you’ve gotten feedback on this? This is a great use of wp with dropdowns, but I too have noticed slightly erratic mouseover behavior on the menus– Safari, Firefox 3 on Mac, IE 6 on Windows XP.
Thanks, though, Aaron, for the great dev! Great use of menus, and something I’ve been needing for a while.
Reply to Johni am trying to impliment this on my blog theme Oh So Very! and when I add the script, and check out my blog page it is completely blank. it seems that first script when added to the header.php file is the culprit….i know i am probably doing something wrong on my end…any help would be greatly appreciated! (i currently took the code off the blog page, so people have access to it)
Reply to Sarahok i changed themes and figured out how to add the menu, but i can’t get it to be a dropdown menu. Also, how can i add both pages and categories to the same menu?> I apologize in advance if I sound lost with all of this….because i am
Reply to Sarahcheers for this - just have to go in and mess about with it all. As my JavaScript skills are basically rubbish you’ve saved me laods of time.
Reply to MichaelThis is what I was looking for. I’ve tried it on my localhost and it works well. Thanks
Reply to ColeThanks for the code but I do have a question.
You said the following:
To activate it, change your theme’s tag to
Where do we exactly go to change the tage to ??
Reply to davidI implemented it but the dropdown thing is not working.Can someone advice me on what is wrong. my site is http://www.reviewmirchi.com
Reply to Dheeraj SInghIt doesn’t look like you changed the body tag as mentioned in the original post.
See the section at the end of the last bit of code in the post.
See my other comment about how to correct the code.
Reply to caseycan you make a plugin for wp? thx..
Reply to dizangor where can i find a plugin.
I just installed this but the drop down menus aren’t showing. Just the “top” categories. Any advice? thanks
diysrc.com
Reply to AdamThe drop-down menu may not work, because of the gap is not closed. Change tag to the following (as you see, with the closed gap):
body onload=”mbSet(’menu’)”;
and script will finally start working. Hurrey! )))
Reply to valenkiWhy not just use Suckerfish (an 11-line Javascript) instead of your 100-line script? It doesn’t throw errors and simply works, without extra markup and “classitis.”
Reply to CodeKillerMy code works on (theoretically) infinate levels of menus. The suckerfish requires a lot of work to get multiple levels as you can see inthis post.
Each level has to be styled individually by hand which makes it close to worthless in a dynamic setting such as blog categories.
If you need one level of dropdowns, then by all means, use suckerfish, but I found it didn’t work for what I needed it to do.
Reply to AaronIf I use this in my sidebar, how would I edit it so that the menus appear to the right of the category, instead of underneath it?
Reply to Sam