Skip to content

Effective Dropdown Menus With WordPress

This article is taken from Packt’s “WordPress 2.8 Theme Design” with permission. A review of the book is coming soon. I don’t agree with everything that’s said, but I’ve decided to publish it as the overall jist of the post will be beneficial to many.

This is the nice thing about WordPress it’s all “dynamic”. Once you install WordPress and design a great theme for it, anyone with the right level of administrative capability can log into the Administration Panel and add, edit, or delete content and menu items. But generally, when people ask for “dynamic menus”, what they really want are those appearing and disappearing drop-down menus which, I believe, they like because it quickly gives a site a very “busy” feel.

I must add my own disclaimer: I don’t like dropdowns. Before you get on to my case, I will say it’s not that they’re “wrong” or “bad”; they just don’t meet my own aesthetic standards and I personally find them non-user friendly. I’d prefer to see a menu system that, if subsections are required, displays them somewhere consistently on the page, either by having a vertical navigation expand to display subsections underneath, or showing additional subjections in a set location on the page if a horizontal menu is used.

I like to be able to look around and say, “OK, I’m in the New Items | Cool Drink section and I can also check out Red Dinks and Retro Dinks within this section”. Having to constantly go back up to the menu and drop-down the options to remind myself of what’s available and what my next move might be, is annoying. Still haven’t convinced you not to use drop-downs? OK, read on.

So you’re going to use dropdowns. Again it’s not “wrong”; however, I would strongly caution you to help your client take a look at their target users before implementing them. If there’s a good chance that most users are going to use the latest browsers that support the current JavaScript, CSS, and Flash standards, and everyone has great mobility and is “mouse-ready”, then there’s really no problem in going for it.

If it becomes apparent that any percentage of the site’s target users will be using older browsers or have disabilities that prevent them from using a mouse and will limit them to tabbing through content, you must consider not using drop-down menus.

I was especially negative about drop-down menus as, until recently, they required bulky JavaScripting or the use of Flash, which does not make clean, semantic, and SEO-friendly (or accessible) XHTML. Enter the Suckerfish method developed by Patrick Griffiths and Dan Webb.

This method is wonderful because it takes valid, semantically accurate, unordered lists (WordPress’ favorite!), and using almost pure CSS, creates dropdowns. The drop-down menus are not tab accessible, but they will simply display as a single, clear unordered list to older browsers that don’t support the required CSS.

IE6, as per usual, poses a problem or two for us, so there is some minimal DOM JavaScripting needed to compensate and achieve the correct effect in that browser.

If you haven’t heard of or worked with the Suckerfish method, I’m going to recommend you to go online (right now!) and read Dan and Patrick’s article in detail (

More recently, Patrick and Dan have revisited this method with “Son-of-a-Suckerfish”, which offers multiple levels and an even further pared down DOM JavaScript. Check it out at

I also suggest you play around with the sample code provided in these articles so that you understand exactly how it works. Go on, and read it. When you get back, I’ll review how to apply this method to your WordPress theme.

DIY SuckerFish menus in WordPress

All done? Great! As you can see, the essential part of this effect is getting your menu items to show up as unordered lists with sub unordered lists. Once you do that, the rest of the magic can be easily handled by finessing the CSS that Patrick and Dan suggest into your theme’s CSS and placing the DOM script in your theme’s header tag(s), in your header.php and/or index.php template files. Seriously, that’s it!

The really good news is that WordPress already outputs your content’s pages and their subpages using unordered lists. Right-click on the page links in Firefox to View Selected Source and check that the DOM inspector shows us that the menu is, in fact, being displayed using an unordered list.

Now you can go into your WordPress Administration panel and add as many pages and subpages as you’d like (Administration | Page | Add New). You’ll use the Page Parent tab on the right to assign your subpages to their parent.

If you installed the pageMash plugin, it’s even easier! You can drag-and-drop your created pages into any configuration you’d like. Just be sure to hit the Update button when you’re done.

Once you’ve added subpages to a page, you’ll be able to use the DOM Source of Selection viewer to see that your menu is displayed with unordered lists and sublists.

Applying CSS to WordPress

We’re going to use the new and improved “Son-of-a-Suckerfish” method so that our menu can handle multilevel dropdowns. To start, let’s just take Dan and Patrick’s suggested code and see what happens. Their unordered list CSS looks like the following:

#nav, #nav ul { /* all lists */
padding: 0;
margin: 0;
list-style: none;
line-height: 1;
#nav a {
display: block;
width: 10em;
#nav li { /* all list items */
float: left;
width: 10em; /* width needed or else Opera goes nuts */
#nav li ul { /* second-level lists */
position: absolute;
background: orange;
width: 10em;
left: -999em; /* using left instead of display to hide menus
because display: none isn't read by screen
readers */
#nav li ul ul { /* third-and-above-level lists */
margin: -1em 0 0 10em;
#nav li:hover ul ul, #nav li:hover ul ul ul, #nav li.sfhover ul ul,
#nav li.sfhover ul ul ul {
left: -999em;
#nav li:hover ul, #nav li li:hover ul, #nav li li li:hover ul,
#nav li.sfhover ul, #nav li li.sfhover ul, #nav li li li.sfhover ul {
/* lists nested under hovered list items */
left: auto;

Now in WordPress, our menu item’s ul is within a div id called top_navlist, and the ul ID is referred to as navlist. There may or may not be lots of other unordered lists used in our site, so we want to be sure that we only affect uls and lis within that top_navlist ID.

We’ll simply tweak the CSS a bit to move items to the left (unfortunately, this works best with horizontal Navs that are positioned from the left instead of the right) and make sure to add #navlist to each element in the Suckerfish CSS. Also, we already have a general #top_navlist and #intTop_navlist rule for the div, so we’ll want to make sure that this only affects the ul within that div by making sure it’s named #navlist. So, our navigation CSS styles now look something like the following:

/*////////// NAV //////////*/
#top_navlist {
position: absolute;
top: 260px;
width: 897px;
#intTop_navlist {
position: absolute;
top: 173px;
width: 897px;
#top_navlist h2, #intTop_navlist h2{
display: none;
#na vlist{
padding: 10px 10px;
margin-left: 0;
border-bottom: 1px solid #ccc;
font-family: Georgia, Times, serif;
font-weight: bold;
#navlist li{
list-style: none;
margin: 0;
display: inline;
#navlist li a{
padding: 11px 30px;
margin-left: 3px;
border: none;
border-left: 1px solid #ccc;
background: #8BA8BA url(images/oo_mag_main_nav.jpg) no-repeat top
text-decoration: none;
color: #253A59;
#navlist li a:hover{
background-color: #9E9C76;
background-position: right -37px;
border-color: #C5BBA0;
color: #784B2C;
text-decoration: underline;
#navlist li.current_page_item a{
border-bottom: 1px solid white;
background-color: #fff;
background-position: right -74px;
#navlist li a:visited { color: #253A59; }
/*suckerfish menu starts here*/
#navlist li ul { /* second-level lists */
position: absolute;
border: none;
margin-top: 10px;
margin-left: 70px;
le ft: -999em; /* using left instead of display to hide menus
because display: none isn't read by screen
readers */
#navlist li ul li a {
display: block;
width: 150px;
font-family: Georgia, Century Schoolbook, Times, serif;
font-size: 12px;
font-variant: normal;
border: 1px solid #666666;
background-color: #ffffff;
background-image: none;
#navlist li ul li a:hover {
background-color: #cccccc;
text-decoration: none;
#navlist li ul ul { /* third-and-above-level lists */
margin: -1em 0 0 7em;
#navlist li:hover ul ul, #nav li:hover ul ul ul, #nav li.sfhover ul
ul, #nav li.sfhover ul ul ul {
left: -999em;
#navlist li:hover ul, #nav li li:hover ul, #nav li li li:hover ul,
#nav li.sfhover ul, #nav li li.sfhover ul, #nav li li li.sfhover ul {
/* lists nested under hovered list items */
left: auto;

Applying the DOM script to WordPress

The last bit is the JavaScript that ensures the hover works in IE6. I call it DOM scripting or the DOM script, but it’s basically just a JavaScript that rewrites your markup (how your DOM is being perceived by IE6) on-the-fly. This drop-down effect relies on the CSS hover attribute. IE6 only recognizes the hover attribute if it is applied to the a (link) entity. IE7 has fixed this limitation and it works similarly for Firefox and other browsers. Dan and Patrick’s script appends the additional .sfhover class to the li items in IE6 only.

You’ll need to add this script to your index.php and/or header.php template pages, inside the header tags. The thing to remember here is that Dan and Patrick named their ul tag’s ID as nav and that’s what this script is looking for. Our ul tag’s ID is named top_navlist, so by simply switching out document. getElementById(“nav”); to document.getElementById(“navlist”);, you’re good to roll in IE.

The full script in your header tags should look like the following (I prefer to tuck it into an include and place it in my home.php (or index.php) and header.php files with a JavaScript include.):

<script type='text/javascript"><!--//--><![CDATA[//><!--
sfHover = function() {
var sfEls = document.getElementById("navlist").getElementsByTagNam
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover=function() {
this.className+=" sfhover";
sfEls[i].onmouseout=function() {
this.className=this.className.replace(new RegExp("
sfhoverb"), "");
if (window.attachEvent) window.attachEvent("onload", sfHover);

For demonstration purposes, I’ve kept the CSS pretty bare boned and ugly; however, when we check this out in our browser, we now see the following:

It’s working ! Remember, with the preceding code, you can have drop-down menus that go three levels deep (Dan and Patrick’s HTML Dog article shows you how to make it handle as many levels as you’d like).

Control those dropdown levels!
As cool as SuckerFish drop-downs are, refrain from going overboard on those levels! Cascading levels can become really tedious for a user to mouse through and can turn a site with a “busy feel” into a total mess. You’ll find that, with a little care, you can easily organize your site’s page content so that it only requires two levels. From there, if you really need it, you can add an occasional third level without creating too much user distraction.

Allowing only selected pages to display

In our theme, we used the wp_list_pages() template tag to display our pages. You can amend the template tag with an exclude parameter that will hide the pages we don’t want to see, including their subpages (for example, wp_list_pages(“exclude=9&title_li=” ); ). You do have to know what the page’s ID number is. (You can temporarily set your permalinks to “default” to see the page’s ID number in the site’s URL.) The pages themselves will still be available for viewing if you know their direct URL path. Read more about it at

Hiding pages the easy way with pageMash

If you have intalled the pageMash plugin by Joel Starnes, displaying and hiding pages is super easy! Simply select hide from the option next to your page. The page will still be available via its permalink URL, but will not display in your drop-down menu.

At this point , all that’s left is fixing up the CSS to make it look exactly the way you want. There you go, semantic, SEO, and as accessible-as-possible dynamic menus in WordPress.

Drop-down menu plugins: Now you’re probably already thinking, “Wait, this is WordPress;%20 maybe there’s a plugin” and you’d be right! By searching the “Extend” section of the site, you’ll find that there are a handful of WordPress plugins that allow for drop-down menus under different conditions. Ryan Hellyer has written a plugin that uses the “Son-of-a-SuckerFish” method that we reviewed in detail earlier. You can review it at

Yay! 🎉 You made it to the end of the article!
Alex Denning

Most Voted
Newest Oldest
Inline Feedbacks
View all comments
December 30, 2011 3:17 am

Thanks for your great post.
Normally i am finding how to change the thesis drop down menu width. and i get it from your post.


seattle dan
November 13, 2011 9:12 pm

This approach works just as well on traditional (non WP) sites and is SEO-friendly as well.

Ben Demsing
November 11, 2011 10:30 pm

I liked Packt’s book as well. Not a big fan of multilevel dropdowns though. The latency factor can make it awful to use.

canndy girl
March 30, 2011 8:31 am

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!

(Anti) Social Lists 2/21/10 | (Anti) Social Development
February 21, 2010 12:28 pm

[…] Effective Dropdown Menus with WordPress – Methods of implementing dropdown menus on your WordPress site. […]

Today in WordPress world – 03/02 | Links | WereWP
February 18, 2010 5:30 pm

[…] Effective Dropdown Menus With WordPress | While waiting for the new menu management system that will be developed with WordPress 3.0, Alex Denning gives us a good tutorial on how to create good dropdown menus within WordPress. Leave a Reply Click here to cancel reply. […]

Il meglio della settimana #48 | BigThink
February 6, 2010 10:03 am

[…] Effective dropdown menus with WordPress Creare un menu a discesa sul proprio tema WordPress. […]

February 4, 2010 1:16 am

I use son of suckerfish menus as well, and I’ve found that if you do the SCRIPT tag as “text/javascript” it will always display an “error on page” in IE. even though this doesn’t actually cause any problems in the browser, I’ve had clients complain. changing it to “application/javascript” seems to takes care of the issue.

Ed Hudson
February 3, 2010 10:11 pm

Good content and information, but I almost went blind trying to read it with these color combinations… sheesh…

February 3, 2010 12:13 pm

This is cool. TFS.

Or start the conversation in our Facebook group for WordPress professionals. Find answers, share tips, and get help from other WordPress experts. Join now (it’s free)!

Would love your thoughts, please comment.x