Making the WordPress Menu Smarter
Why do this? Consistency, style, and usability. It’s a progressive enhancement.
It was almost a year ago that I published the article “Building a Dynamic WordPress Nav Menu” in which I described the how-to of my BeastBlog v2 theme’s navigation menu. I thought I’d revisit the subject since it’s been revisited through my projects lately. The menu’s gotten smarter. This won’t be needed on many sites, and WordPress blogs without “pages” wouldn’t need this, but on others it might be a nice enhancement. That’s your call.
Code It
I have added comments within the code that will hopefully explain what’s what. If you don’t know, this code would go in your sidebar.php
file (or whatever file has your pages navigation). This should be ready to copy and paste without modification.
<!--Begin an unordered list the ID is for the bookmark, the class is for the style (so I can have other lists with the same styling as seen on RedScrubs.com)--> <ul id="nav" class="btn"> <!--IF the current page is the 404 page, note the added error class--> <?php if(is_404()) { ?> <li class="current_page_item error"><a href="#">404 Error</a></li> <?php } ?> <!--IF the current page is the search results page--> <?php if(is_search()) { ?> <li class="current_page_item"><a href="#">Search Results</a></li> <?php } ?> <!--IF the current page is a single post--> <?php if(is_single()) { ?> <li class="current_page_item"><a href="#">Selected Article</a></li> <?php } ?> <!--IF the current page is a category page, but not an "older" page--> <?php if((is_category()) && (!is_paged())) { ?> <li class="current_page_item"><a href="#">Content Category</a></li> <?php } ?> <!--IF the current page is an archive page, but not a category--> <?php if((is_archive()) && (!is_category())) { ?> <li class="current_page_item"><a href="#">Archived Content</a></li> <?php } ?> <!--IF the current page is an "older" page--> <?php if(is_paged()) { ?> <li class="current_page_item"><a href="#">Older Entries</a></li> <?php } ?> <!--IF the current page is the home page but not an "older" page--> <?php if((is_home()) && (!is_paged())){ ?> <li class="current_page_item"><a href="<?php echo get_settings('home'); ?>">Home Page</a></li> <!--ELSE the current page must not be the home page--> <?php } else { ?> <li><a href="<?php echo get_settings('home'); ?>">Home Page</a></li> <?php } ?> <!--This is the actual WordPress menu. This one is set to observe your page order number (set in the page editor’s sidebar), with no added heading since I add that on my own--> <?php wp_list_pages('sort_column=menu_order&title_li='); ?> <!--The RSS feed link--> <li><a class="rss" rel="alternate" href="<?php bloginfo('rss2_url'); ?>" title="Really Simply Syndication">Subscribe RSS</a></li> <!--Terminate the list--> </ul>
Using the scripting above, you can easily take it a step further offering post titles, archive dates, and category names instead of generic terminology. All that’s need are a few WordPress functions in lieu of the generic fixed text. There are limitations, though. Take, for instance, my use of links on the “current” pages. In the case of my additions this was a choice, but not one fueled by madness. The default WordPress menu provides a link to current pages offering only a current_page_item
class on the corresponding list item (li
). My offering the current pages as self-targeting links is just me going with the flow.
Style It
Now for some styles to make it look nice. What’s shown above is from a site I did recently minus one small change — the example site shows the post title in the menu instead of “Selected Article” and I did this by using <?php the_title(); ?>
instead of the text. The styles below are copied and pasted from the same site minus the background images and a few other non-applicable selectors and style properties.
/* Basic list styling */
ul.btn {
list-style-type : none;
text-align : center;
}
/* Default styling for the links. a:visited
not included here but
should be on larger menus */
ul.btn a, ul.btn a.rss {
background-color : #660000;
padding : 8px 4px 5px 4px;
font-size : 0.9em;
margin-bottom : 5px;
width : 155px;
height : auto;
color : #f0d1a9;
font-weight : bold;
display : block;
text-decoration : none;
border : 1px solid #000;
}
/* This is needed for IE if bottom margin is used on the links */
ul.btn li {
margin-bottom : 5px;
}
/* Hover styling for the links */
ul.btn a:hover {
background-color : #990000;
color : #f6eadb;
}
/* Focus/active styling for the links (mainly for keyboard users) */
ul.btn a:focus, ul.btn a:active {
background-color : #440000;
color : #eee;
outline : 0;
/* For me this is new. Gets rid of the dotted outline.
Thanks goes to Eric Meyer’s Resetting Again */
}
/* Make the RSS link different, there is no “current” page state for
this link… not needed */
ul.btn a.rss:hover, ul.btn a.rss:focus, ul.btn a.rss:active {
background-color : #ff6600;
color : #000;
outline : 0;
}
/* Make the RSS link different, there is no “current” page state for
this link… not needed */
ul.btn li.current_page_item a,
ul.btn li.current_page_item a:hover,
ul.btn li.current_page_item a:focus,
ul.btn li.current_page_item a:active {
background-color : #666600;
color : #fff;
cursor : default;
text-transform : uppercase;
outline : 0;
}
/* Current page style for the 404 error (only one state needed) */
ul.btn li.error a,
ul.btn li.error a:hover,
ul.btn li.error a:focus,
ul.btn li.error a:active {
background-color : #bb0000;
color : #fff;
outline : 0;
}
The styles above are designed for use on pages directly off the root (http://yoursite.com/page/
). If you want to offer sub-pages, more styling will be needed and more classes used, as I did on my company’s site (I posted the styles there just in case someone might be interested).
Why do this? Consistency, style, and usability. It’s a progressive enhancement for visual users. I can’t say it has any accessibility advantage, but as long as it doesn’t have an accessibility disadvantage associated with it, it might a good enhancement.
David Zemens - 1955 Design responds:
Posted: January 30th, 2008 at 5:49 am →
Being a student of yours, Mr. Professor, I noticed that you implemented something similar to this on your most recent revision of your Green Methods website. I thought it was a very unique approach to WordPress navigation and I was able to cobble it into use on a site I was working on. Thanks for sharing your thought process and your code.
Mike Cherim responds:
Posted: January 30th, 2008 at 10:17 am →
You’re very welcome, David.
Jermayn Parker responds:
Posted: January 30th, 2008 at 9:58 pm →
Ok I have winged about WP lack of menu-ing, so now I am going to have to have a look at this code more closely and see if I can get a hang of what you have done!
Thanks for posting this Mike!
JOsh responds:
Posted: February 13th, 2008 at 4:57 am →
I have tried to use your code above but I am running into a problem and I could use some help. Please!
I have taken the default theme and made the following mod. I have used a loop on a custom template which is my “home” page to pull in the 5 most recent posts. However, I do have a “Blog” link in the nav which serves the 10 most recent postings.
I have this working fine by using the Options page and setting the home template to be the front page and the posts page to be the blog.
So the problem is this…I can get all the other pages to react dynamically and show the user location by the css hooks but the “blog” link will not behave.
I have tried many different techniques such as:
http://wordpress.org/support/topic/113190
http://www.webdesignerwall.com/tutorials/wordpress-theme-hacks/
Please spare a few moments and offer me some advice. I think if I did a straight up blog things would be cool but since I am pulling in 5 posts on the HP and then also haveing a blog too I am thinking this must be causing a problem?
Thanks for your article,
Josh
Mike Cherim responds:
Posted: February 13th, 2008 at 9:40 am →
Hi Josh. I know the situation well. On my GreenMethods site I have a fixed home with a weblog main. I published on that site what I did (both scripting and styles). I used this script to help me out there. This should help you.
Jeff Houdyschell responds:
Posted: March 27th, 2008 at 7:36 pm →
Mike how can I trick the nav menu, into thinking that home isn’t index.php or the blog loop when using a static front page option? Example - I create a page called the name of the site, and set it as the front page, another page called blog is set for the loop. When using a nav menu that highlights the current page how can I make these highlight correcty?
I have a live sample using the Violator theme here: http://www.wordpressmax.com/pips/
And the code:
current_page_itempage_item”>“>Home
Mike Cherim responds:
Posted: March 27th, 2008 at 7:41 pm →
Hi Jeff. If it’s a page you could refer to the ID. Or, you could hand code a bit exploding the URI. That’s what I did on my company’s site. The technique is actually described on the site on the nav help page. It uses a technique I discuss on another site if you need more info about it. It’s a pretty stable method.
Daniel Anderson responds:
Posted: April 16th, 2008 at 8:54 am →
Great Article Mike. I can’t wait to try this out in m next project. i will post the results when I have tested it.
Cheers
Daniel