WordPress Menu Tricks

In this post I’m going to show you how to take WordPress Menu Editing to the next level. You’re going to learn how to use Primary and Secondary menus in your WordPress theme; Add descriptive sub-title links to your menu items like some popular WordPress themes and sites; Filter the menu of a WordPress theme; Add special CSS classes to wp_page_menu; and finally, how to hand-code your own WordPress menu for the ultimate in control.

Here’s how to make your WordPress menu jump through hoops.

Primary and Secondary Menus

This one’s really easy with wp_page_menu. Instead of adding it once to our theme, we’ll add it twice!—but including only select pages each time.

<?php wp_page_menu('exclude=24,27,28&amp;menu_class=menu menu-primary'); ?>
<?php wp_page_menu('include=24,27,28&amp;menu_class=menu menu-secondary'); ?>

Because wp_page_menu generates all the code we’ll need for a menu we simply have to exclude pages from the first menu and include some in the other. With new menu classes of menu-primary and menu-secondary we’re all set.

Here’s how to do it with a Thematic Child Theme—or any in any Child Theme where the parent theme is using wp_page_menu. Also easy, but with wp_list_pages so we can avoid any CSS styling problems with multiple drop down menus. Just use this code snippet in your Child Theme functions file.

// Remove the default Thematic Access
function remove_thematic_actions() {
    remove_action('thematic_header','thematic_access',9);
}
add_action('init','remove_thematic_actions');

// Recreate the Thematic Access with menu-primary and menu-secondary
function childtheme_page_menu() { ?>
	<div id="access">
		<div class="skip-link"><a href="#content" title="<?php _e('Skip navigation to the content', 'thematic'); ?>"><?php _e('Skip to content', 'thematic'); ?></a></div>        
        <?php wp_page_menu('exclude=24,27,28&amp;menu_class=menu menu-primary'); ?>
        <div class="menu menu-secondary">
            <ul>
                <?php wp_list_pages('title_li=&amp;include=24,27,28'); ?>
            </ul>
        </div>
    </div><!-- #access -->    
<?php }
add_action('thematic_header','childtheme_page_menu','9');

Adding Sub-Titles To Menu Links

Sometimes you’re going to want to add descriptive text underneath your WordPress menu links like in the Grid Focus theme,

grid-focus

or like you’ve seen around the web on static, and non-WordPress sites.

creative-display

Usually this is done by hand editing the menu but it can be accomplished using WordPress custom fields. Simply add a custom field to the pages in question named “subtitle” with a value of “whatever you want your descriptive subtitle text to be”. Then make sure you have the following code snippet (adapted from the clearskys.net blog ) in the functions file of your WordPress Child Theme—as long as the parent theme is using wp_page_menu. If you’re simply editing a WordPress theme directly, cut the code from the childtheme_page_menu function and use it to replace your existing menu in header.php.

// Adds descriptive text to link titles
// With help from http://blog.clearskys.net/2008/12/17/how-to-adding-menu-sub-titles-to-a-theme/
function sub_page_list() {
global $wpdb;
$sql = "SELECT p.ID, p.post_title, p.guid, pm.meta_value FROM " . $wpdb->posts . " AS p LEFT JOIN ";
$sql .= "(SELECT post_id, meta_value FROM " . $wpdb->postmeta . " AS ipm WHERE meta_key = ‘subtitle’) ";
$sql .= "AS pm ON p.ID = pm.post_id ";
$sql .= "WHERE p.post_type = ‘page’ AND p.post_parent = 0 AND p.post_status = ‘publish’ ";
$sql .= "ORDER BY p.menu_order ASC ";
$sql .= "LIMIT 0, 10";
$rows = $wpdb->get_results($sql,OBJECT);
if($rows) {
foreach($rows as $row) {
echo "<li>";
$link_url = get_permalink($row->ID);
echo "<a href="$link_url"" . "">$row->post_title</a>";
echo "<span style="display:block;">$row->meta_value</span>";
echo "</li>";
}
}
}

// Filter the menu to add the list
function childtheme_page_menu() { ?>
<div class="menu">
<ul>
<?php if (is_front_page()) { ?>
<li><a href="<?php bloginfo(‘home’) ?>/" title="<?php echo wp_specialchars( get_bloginfo(‘name’), 1 ) ?>" rel="home">
Home <span style="display:block;">This is the home page</span>
</a></li>
<?php } else { ?>
<li><a href="<?php bloginfo(‘home’) ?>/" title="<?php echo wp_specialchars( get_bloginfo(‘name’), 1 ) ?>" rel="home">
Home <span style="display:block;">Return to the home page</span>
</a></li>
<?php } ?>

<?php sub_page_list(); ?>

</ul>
</div>
<?php }
add_filter(‘wp_page_menu’,’childtheme_page_menu’);

Adding Class To Your Menu List

One of the problems of using wp_page_menu is that the HTML is all wrapped in the function. You can’t get at it. Which is a pain if you want to use the function but also want to add special classes for implementing javascript drop-down menus or do some trickier CSS without giving yourself a headache. Luckily, you can filter it. Here’s how to filter wp_page_menu and add a unique class to the first instance of the ul tag, using PHP’s preg_replace to find the first ul tag and adding in id and class attributes.

// Add ID and CLASS attributes to the first <ul> occurence in wp_page_menu
function add_menuclass($ulclass) {
return preg_replace('/<ul>/', '<ul id="nav" class="something-classy">', $ulclass, 1);
}
add_filter('wp_page_menu','add_menuclass');

Basically, wp_page_menu can be filtered with any content (I often use “bacon” as test content—mmm, bacon) which is handy to know if you ever want to code your own custom menu.

Hand Coding a Dynamic WordPress Menu

And sometimes you are going to want to code your own menu. I’ve done it and I’ll probably do it again. You could just create a simple list of links but it’s better to create a dynamic list that checks to see if you’re currently on a particular page and adds a class of current_page_item to the list item if you are. This’ll let you create more usable menus with a little bit of CSS.

If you’re doing this in a Child Theme and the Parent Theme is using wp_page_menu this’ll be pretty straight forward, we’re just going to filter wp_page_menu. And if you’re editing your theme directly just grab the code out of the function in this snippet and plop it into the appropriate spot of your theme.

function childtheme_menu() { ?>
<div id="menu">
<ul>
	<li class="<?php if ( is_page('about') ) { ?>current_page_item<?php } else { ?>page_item<?php } ?>"><a href="<?php echo get_option('home') ?>/about/" title="About This Blog">About</a></li>
	<li class="<?php if ( is_page('advertising') ) { ?>current_page_item<?php } else { ?>page_item<?php } ?>"><a href="<?php echo get_option('home') ?>/advertising/" title="Advertise on My Blog">Advertise</a></li>
	<li class="<?php if ( is_page('contact') ) { ?>current_page_item<?php } else { ?>page_item<?php } ?>"><a href="<?php echo get_option('home') ?>/contact/" title="Contact Me">Contact</a></li>
</ul>
</div>
 
<?php }
 
add_filter( 'wp_page_menu', 'childtheme_menu' );

The key in this example is what’s happening in the list items between the li tags. If you look at line 4 you’ll see we’re checking to see if we’re on the about page, and if we are we get a class of current_page_item, otherwise, page_item. Simple!

57 thoughts on “WordPress Menu Tricks

  1. Something to add to make it more complete is how to filter the list and add nofollow to all, or even specific links based upon an array, which can then be done conditionally based upon page type.

  2. Great blog! I love the formatting tweaks that really help a site to stand out while making it easier to update.
    Just a quick FYI: The email version of the blogs do not wrap the text properly. Could be the header/footer image width, or a fixed width encoded somewhere.

    Best wises!

  3. Daniel Young says:

    Thanks for posting this. Just to let you know, the code for “Adding Sub-Titles To Menu Links” produces a small bug. Line 16:


    echo "$row->post_title";

    produces double quotes after the URL (which invalidates XHTML), something like this:


    About UsCompany History

    Also, the title attribute is only preserved for the “Home” link. How would I modify the code so that it displays the title attribute for the other links as well?

    Thanks!

  4. Pingback: Monday Morning Roundup - April 6, 2009 — WPCandy — WordPress Themes, Plugins, Tips, and Tricks

  5. Pingback: Recursos para Wordpress - I | Pupurri.es

  6. Pingback: wp_page_menu 函数使用详解 at 站趣-分享建站的乐趣

  7. Pingback: The Huff Family Blog » WP Menu Stuff

  8. Great tips!

    I also noticed the double quotes in Adding Sub-Titles To Menu Links that Daniel mentioned. Here’s how I fixed it, and also how I modified the element. I wanted the as part of the link element for styling purposes, and I also moved the "display:block" declaration and put it into the style rule. Here’s my tweaked version, lines 16-17:

    echo "$row->post_title";
    echo "$row->meta_value
    ";

  9. Pingback: Monday Morning Roundup - April 6, 2009 « Internet Turnkey Websites

  10. ts says:

    Thanks, useful. But I think I find it easier to do menus with a custom loop and designated custom fields indicating the menu level and additional menu content, like images, for a graphic menu. The Flutter-plugin is occasionally helpful here. It’s easier to change around in page-management than in the theme. After all, you’re still excluding and including pages in the theme, not in the backend.

  11. Oh cool, I’ve been scouring the web looking for a wordpressified hack to achieve this. I reckon it’s a plugin which would get some real attention should anyone develop something, hint hint! :)

    I was trying to achieve the same thing using the link_after parameter for wp_list_pages, btu it doesn’t automatically allow a custom field value in the code :(

    Anyone know of something which could solve that?

  12. Aah shucks, seems my understanding of this code is a little too poor to mod it for a normal non-thematic non-child theme.

    I also tried the functions.php solution from clearskys btu ended up with blank page.
    I’m gonna live with writing sub title in the WordPress title field for now, works ok if u style it correctly. Just means I have to generate my head title using a custom field or something.

    I was really hoping to could somehow add a custom field value in span tags within the link_after parameter for wp_list_pages, seems it’s not possible. :(

  13. Ben fiddling around with a few solutions like this over the last few days. Finally got the clearskys.net function working with the help of @urbanrenewal who modified the code a little.

    So no there’s the problem of the dynamic classes, no childpage drop downs & exclude page functionality not working.

    Anyone know what can be thrown in between lines 17 & 18 to echo the child page UL for any child pages?

    • Anthony Calzadilla says:

      I’ve been fighting with thte sub-titled links too. I’ve been trying to figure out how to put the dynamic classes BACK into the list items but so far no luck. I posted in the forums but still no help there either.

  14. Any ideas how to simply INclude menu items to make a nav bar, instead of EXcluding them?

    I want to build a special menu based on certain pages only.

  15. Pingback: Sophistigrunge - Free WordPress Theme | Theme Lab

  16. does anyone know how I can add menus at the bottome of my page? I want to add “about us” or “contact us” or “FAQ” at the bottom of the page but I cant seem to figure it out.

    appreciate any help I can get.

    Thanks.

  17. Pingback: Wordpress: Tutorials and Resources for Designers and Developers

  18. Pingback: Jon Kristian » Menu Subtitles

  19. Pingback: Download Demus Design wordpress themes | Sophistigrunge – Free WordPress Theme

  20. Pingback: Add Wordpress Menu Description | The Template Blog

  21. Hi All

    This rewriting of the menu code causes you to loose the dynamic classes. This makes styling of different menu items difficult. I have a pretty simple plug-in that allows the use of wp_page_menu(). The plug-in is a rewrite of Page Lists Plus to strip out all of the extra code to make this plug-in as simple as possible. It is available on my site if you are interested.

    Dave
    TheTemplateBlog

  22. Pingback: 100+ Massive Wordpress Tutorial Collection | tripwire magazine

  23. Pingback: RS16 – Free WordPress Theme | Theme Lab

  24. robin says:

    For Primary and Secondary menus, how to designate what page goes in what menu? do I use the number generated in the class code, i.e.,128 as in “page_item page-item-128″?

    sorry if this is obvious, alas, I’m PHP illiterate. thank you!

  25. Pingback: 9 Wordpress Tricks and Tutorials « Er.Krushna Chandra Muni :: Professional Web Developer | Website Design Orissa | Website Design Bhubaneswar | Website Design India | Website Design New Zealand | Website Design Auckland

  26. Pingback: Doliaku! :::: » links for 2010-02-26

  27. Pingback: Creating custom nav’s with wordpress

  28. Pingback: Wordpress Kullanım ve geliştirme kaynakları | web tasarım ve magazin

  29. WordPresser says:

    How to remove the title tag from the menu links? It makes no sense that when you hover the mouse cursor over a menu item to show a tooltip that just contains the same text! in the menu item being hovered over.

    example, this is always generated:
    a href=”some link” title=” menu item”

    how to just generate
    a href=”some link”

    You do have it implemented without the title tag on your site Ian, so tell us how you removed it :)

  30. anything that has a title with “taking it to the next level” is surely wort a read.

    But is there a way to create a custom field that on rollover shows a tool tip in a yellow box?

    i assume the css would be starting with.
    #box{
    background;yellow;
    boring:bla bla bla;
    }

    then im lost!

  31. Thanks for the tips. How about adding a .class to li menu items? Say you want to dynamically highlight your menu and you have your body ID’s from the URL – now you need to have menu items (li’s) with the same class as the body ID and with css you could do something like:
    #home .home {color: red ;} to highlight your current menu item.

    So again: how do you set a class to a li menu item? :)

    Thanks,
    Alex

    • Toni L says:

      I’m trying again since it didn’t work in the first place so here comes:

      Note! Everything comes for (functions.php)

      1)First I need the remove the default header

      function remove_thematic_menu() {
      remove_action('thematic_header','thematic_access',9);
      }
      add_action('init','remove_thematic_items');

      2)Then we make the new custom menu

      add_action( 'init', 'register_my_menu' );

      function register_my_menu() {
      register_nav_menu( 'primary-menu', __( 'Primary Menu' ) );
      }

      3) Then we construct the menu

      function childtheme_access(){ ?>

      [div id="access"]
      [div class="skip-link"]
      [a href="#content" title="
      ">
      [/a]
      [/div]

      4)Here we do the magic

      [div id="menu"]
      'primary-menu', 'menu_class' => 'sf-menu' ) ); ?>
      [/div]
      [/div]

      Note! We are replacing the real tag signs with ‘[' and ']‘

  32. I am working on theming my site, which I plan to use for showcasing of my work as a web-developer.

    Editing wordpress php for themes doesn’t appear to be rocket surgery, yet I am relatively new to the platform and I don’t know all ins and outs as well as functions of the api. My question is this. I create the custom menu, through a custom menu widget, and now I want to use the same function that generates the UL for the widget in another part of the site, namely in the header menu. What would it be?

  33. so. since the wp 3.0 update there are a lot of new custom menu features. one being descriptions for menu items. could we get some updated advice on the easiest way to incorporate the description as sub-titles to menu links instead of using individual pages’ custom fields? thanks Ian (or anyone else that has got this working).

    p.s. i’m definitely comin back to thematic from using hybrid…don’t know why i left. thanks for creating something awesome.

  34. Jill says:

    Hmmm. My comment doesn’t seem to have posted properly. Here’s my function file code again:

    // Remove the default Thematic Access
    function remove_thematic_actions() {
    remove_action(‘thematic_header’,’thematic_access’,9);
    }
    add_action(‘init’,’remove_thematic_actions’);

    // Recreate the Thematic Access with menu-primary and menu-secondary
    function childtheme_page_menu() { ?>

    <a href="#content" title="”>

    <?php }
    add_action('thematic_header','childtheme_page_menu','9');

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s