Building a Dynamic WordPress Nav Menu

Posted February 8th, 2007 by Mike Cherim

More and more people are using WordPress as a Content Management System (CMS), and for good reason. It’s well supported, produces good mark-up, and it’s flexible. But when using it as a CMS it suddenly becomes very important to optimize the support of WordPress “Pages.” Unlike post, archive, and category links, a web site’s “Pages” have the utmost importance. This article will teach you how to produce a dynamic WordPress “Pages” navigation menu that looks good and behaves as a main navigation menu should.

To Begin With…

The first thing to consider is placement. For a vertical menu I would suggest placing the code I will supply in the sidebar.php file under the “sidebar” div if you have one. And if you’re going for a horizontally-displayed navigation menu I suggest adding the code in the header.php file underneath your main <h1> heading.

The Markup

Here’s the mark-up you will want to place in your file of choice.

 <!--See Note 1-->
 <ul id="nav">
 <!--See Note 2-->
  <?php if(is_home() && !is_paged()){ ?>
   <li class="current_page_item">
    <a href="<?php echo get_settings('home'); ?>" title="You are Home">Blog Navigation</a>
   </li>
 <?php } else { ?>
  <li>
   <a href="<?php echo get_settings('home'); ?>" title="Click for Home">Blog Home</a>
  </li>
 <?php } ?>
 <!--See Note 3-->
 <?php  wp_list_pages('sort_column=menu_order&title_li='); ?>
 <!--See Note 4-->
  <li>
   <a class="rss" rel="alternate" href="<?php bloginfo('rss2_url'); ?>" title="Really Simply Syndication">RSS Feed</a>
  </li>
 </ul>

Markup Notes

Now to explain what’s what in the script above.

Note 1
I first identify the menu with a “nav” ID. This isn’t needed for styling since WordPress generates the list-item classes in its core, but I’m using it anyway as it serves two purposes. The “page_item” class doesn’t really need to be there. Go with it; editing core files isn’t advisable as it’ll impede upgrading WordPress. The main reason I offer this is to use #nav as a fragment identifier so as to use it as a bookmark link target for a “Jump to Navigation” link: <a href="#nav">Jump to Navigation</a> (Code 1)
Note 2
This is a bit of page negotiation since I want the menu to have a home page link — something not provided on the page list by default. When you’re on the index this will say “Blog Navigation” and be styled as a current page link, but if you’re on any other page, including a “paged” home (when you view older posts via a page turner link), the link will say “Blog Home” instead and will look clickable instead of like the “current page” style. (Code 2)
Note 3
This is the meat and potatoes so to speak. This is the code for the dynamic menu produced by the WordPress core. This will produce page links in list item tags: <li>. Each will bear the “page_item” class except the current page where it’ll also bear the “current_page_item” class. I use only the latter. This conditional tag has two parameters in the function:
  1. sort_column=menu_order — This allows you to use the page ordering feature built into WordPress. This ensures you can put your page links in an order you deem logical.
  2. title_li= — This parameter can contain data such as <h2>Heading</h2>. If it is removed, the word “Pages” will display between the dynamic links and the home page link. If the <h2> heading elements are left blank the word “Pages” will display in the same spot. This would be okay if there was no home page link but that’s not the case, so I give the whole parameter a null value. I could give it a “0” (zero) I suppose. (Code 3)
Note 4
This last link is optional. Use it if your want a prominent link to your Really Simple Syndication or RSS feed. I give this link a special “rss” class so I can give it a unique background image in the style sheet. I add it to the “ul#nav” selector in the style sheet so the same attributes and properties are applied. I then give it a background image in a new CSS block — I’ll show you what I mean next. (Code 4)

Styling the List

What follows are some styles for your Cascading Style Sheet (CSS). These styles will produce block-level links in the vertical format. You can modify these styles to get your desired look, add backgrounds, change colors, anything you wish. To make it a horizontal menu you’ll want to float it left (right reverses the order so you’ll have to modify the scripting and markup) and list items will need the display property, “inline.” You can also give the unordered list a width and center it with margin-auto. You will also want to center-align the text, probably…

Nonetheless, this will offer you a simple copy and paste beginning. (All of this should be put in a container div of 200 pixels with 10 pixels of padding unless you decide to modify dimension and/or units, or you’re doing the horizontal thing.)

 /* This styles the unordered list element to remove bullets and align the text */
 ul#nav {
   list-style-type : none;
   text-align : right;
 }

 /*
  This styles the links. It’s a block-level link and the text is positioned
  with padding. Other styles are defined: width, colors, text attributes, etc.
 */
 ul#nav a, ul#nav a.rss {
   background-color : #d3d3a7;
   padding : 15px 5px 2px 10px;
   margin-bottom : 10px;
   width : 180px;
   height : auto;
   color : #333;
   font-weight : bold;
   font-style : normal;
   display : block;
   text-decoration : none;
 }

 /* This gives the “rss” class link a background image */
 ul#nav a.rss {
   background : #d3d3a7 url(images/rss.jpg) no-repeat 2px 2px;
 }

 /* This is only necessary for IE6 else the link margins will collapse on hover */
 ul#nav li {
   margin-bottom : 10px;
 }

 /* This removes the default left margin (indentation) */
 ul#nav li {
   margin-left : 0;
 }

 /*
  Now to offer some hover and focus styles. Further specification of focus/active styles
  could be added but I didn’t do it in this example. I didn’t feel it was needed
 */
 ul#nav a:hover, ul#nav a:focus, ul#nav a:active {
   background-color : #669900;
   color : #fff;
 }

 /* This offers up a hover/focus state image for the “rss” class link */
 ul#nav a.rss:hover, ul#nav a.rss:focus {
   background : #669900 url(images/rss_on.jpg) no-repeat 2px 2px;
 }

 /*
  This style the single state of the “current_page_item” class link. Not needed for
  the “rss” class link since that target page won’t display the menu
 */
 ul#nav li.current_page_item a, ul#nav li.current_page_item a:hover,
 ul#nav li.current_page_item a:focus, ul#nav li.current_page_item a:active {
   background-color : #9e9e55;
   color : #fff;
   cursor : default;
   text-align : left;
 }

Miscellaneous

Here’s some general info.

  • You could add to the style info above to support child pages, or sub-pages, but the CSS I provided doesn’t support that link type in a special way — the subpage links and the current page link will both be marked the same way.
  • You could also modify the script part of this menu if you had a static home page. Please note, however, that I’m not sure if a modification is needed to tell the truth. I haven’t tried it in such an application. You tell me.
  • What I have on this site is custom made because I currently have several non-WordPress pages. Thus, if you want to see an example of this menu, please check out the sidebar on my BeastBlog v.2.0 theme support blog, but please know that it is slightly different than what I’m offering here. I added a “btn” class in addition to the “nav” ID. Doing it this way allows advanced theme users — since the theme is publically available — the ability to easily give additional menus the same styling via the “btn” class (because IDs must be unique on any given page while classes can be used repeatedly).
  • In my example, when on the home page, I offer a link. This doesn’t have to be the case. A heading in a list item could be styled, plain text could be offered, what ever you want. I chose to do this instead. Laziness.

17 Responses to: “Building a Dynamic WordPress Nav Menu”

  1. Donny Burnside responds:
    Posted: February 9th, 2007 at 1:19 am

    Nice job with the article. Dugg!

  2. Darwin Hall responds:
    Posted: February 10th, 2007 at 2:16 pm

    Great info Mike. Maybe you should write a book???

  3. Jermayn Parker responds:
    Posted: February 11th, 2007 at 11:38 pm

    Yeah or at least an ebook on Wordpress and how to customise it like you have in your previous articles especially seeing so many people are using Wordpress as a blogging, cms and web tool.

  4. The InterThing… » Dynamic Wordpress Navigation responds:
    Posted: March 3rd, 2007 at 5:00 am

    […] Stumbled upon this today and going through the code now. March 3, 2007 · New Shit · […]

  5. 33king responds:
    Posted: March 3rd, 2007 at 5:02 am

    This is one of the best blog posts I have ever seen

  6. tenterhooks responds:
    Posted: March 6th, 2007 at 12:30 pm

    New Wordpress Menu…

    This blog is “just another wordpress blog”. Problem was I di not like the menu system. So I created my own. With a little fancy footwork and a generous helping of ‘foreach’ I have the css cross-browser drop-down menu of my dr…

  7. tenterhooks » Blog Archive » New Wordpress Menu responds:
    Posted: March 9th, 2007 at 1:23 am

    […] Here is a link to another way to accomplish a dynamic css menu for wordpress: side dynamic menu for pages. While not a drop down or one that is used for all links, it does highlight the page links if that is more important to the blog than the other links available. Tags: Design, Development, menu, modification, wordpress […]

  8. Sheri responds:
    Posted: March 9th, 2007 at 5:51 pm

    Hi Mike, sorry about the double ping. I changed my permalinks and darn Wordpress sent out another ping.

  9. Dave M responds:
    Posted: April 22nd, 2007 at 5:42 pm

    Hi Mike - great post! It helped me modify my main horizontal menu bar to remove the “Home” selection when the home page is already displayed.

    What I’m really trying to find now is a way to add pages to my site without having them automatically show up in the menu. These would be static content pages that I want to link to from other pages and/or posts, but I don’t want them to become menu items.

    And here’s another puzzle I can’t figure out… I have a main Articles page that appears in my menu. I’ve started creating sub-pages of various articles. Now, how do I display all the sub-pages as some sort of clickable index on my main articles page?

    BTW, I’m new to WordPress if you haven’t figured that out already! :-)

    Dave

  10. Wayne Fields responds:
    Posted: May 2nd, 2007 at 11:35 am

    I use this menu for my site layout works wonders but I have one problem.

    Here’s the theme I am working on http://madthemes.com/

    I am trying to recreate my site http://deonya.com so I can use WordPress as a cms

    The problem is I need to set a class to the link that is active so that my menu will change images accordingly
    look at http://deonya.com when you click a link when you on that page the menu image change to a white image to show it as active but using this mod I can get it to work on anything but the home page.

  11. Wayne Fields responds:
    Posted: May 2nd, 2007 at 2:18 pm

    Awesome that worked thanks for writing this it works wonders

  12. Wayne Fields responds:
    Posted: May 2nd, 2007 at 10:58 pm

    I was wondering if its possible to limit the amount of links that will show in the main menu like I have about 5 links I want in the main menu but I need to make other pages but I don;t want there link to appear in the main menu I was trying a few things but my coding is not the best.

Sorry. Comments are closed.




Note: This is the end of the usable page. The image(s) below are preloaded for performance only.