WordPress Menu Tricks

Posted: March 3, 2011 in PHP, Wordpress
Tags: ,

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&menu_class=menu menu-primary'); ?>
<?php wp_page_menu('include=24,27,28&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 ofmenu-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() {
// 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&menu_class=menu menu-primary'); ?>
<div class="menu menu-secondary">
<?php wp_list_pages('title_li=&include=24,27,28'); ?>
</div><!-- #access -->
<?php }

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,

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

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
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">
<?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>
<?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>
<?php } ?>
<?php sub_page_list(); ?>
<?php }

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 filterwp_page_menu and add a unique class to the first instance of the ul tag, using PHP’spreg_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">', $ulclass, 1);

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 ofcurrent_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">
<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>
<?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!

  1. Hello to every one, since I am actually keen of reading this web site’s post to be updated daily. It includes pleasant stuff.

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