Please note, this might be considered a “Go Big, or Go Home” exercise. Please read this entire post before attempting this at home, or on your own site or theme.

This article will be covering the implementation of the wp_nav_menu() function using the wp_list_pages() function as a fallback. The menu will also be centered and support full drop down sub-menu items, or child pages as some would refer to them … and, the menu system now live on this site, too.

The following code will also be released in the free WordPress Theme Shades at version 1.6, and it will also be the basis for the examples used in this post.

Let’s get started …

What We Need

Have a look at the codex pages above for wp_list_pages(), wp_nav_menu, and register_nav_menu to get (more) familiar with the basics of these functions. As this has to do with the use of wp_list_pages() reading the article “Upgrade wp_list_pages() to wp_nav_menu()” may also prove useful.

Although not absolutely necessary, getting a copy of the Shades theme may be handy if you wish to look at the code directly rather than the examples and snippets to follow.

The last part is the CSS to make it all work. This is from a great article written by Matthew James Taylor and can be found here.

On the next page we will look at what to do …

What We Will Do

First we are going to open the functions.php template file and start with adding the following code:

wp_nav_menu( array(
   'theme_location' => 'top-menu',
   'fallback_cb' => 'custom_list_pages'
   ) );

Next we will need to incorporate the fallback menu code via wp_list_pages(), with the following:

function custom_list_pages() {
  if ( is_home() || is_front_page() ) { ?>
    <ul><?php wp_list_pages( 'title_li=' ); ?></ul>
  <?php } else { ?>
    <ul>
      <li><a href="<?php bloginfo( 'url' ); ?>"><?php _e( 'Home' ); ?></a></li>
      <?php wp_list_pages( 'title_li=' ); ?>
    </ul>
  <?php }
}

Both of these functions will need to be included in the custom function that will be the base of our new menu system. The code looks like this:

function custom_nav_menu() {
    if ( function_exists( 'wp_nav_menu' ) )
      wp_nav_menu( array(
			   'theme_location' => 'top-menu',
			   'fallback_cb' => 'custom_list_pages'
			   ) );
    else
      custom_list_pages();
}

Then we need to register the custom function and give it a place to live. This code will accomplish that:

add_action( 'init', 'register_custom_menu' );
function register_custom_menu() {
    register_nav_menu( 'top-menu', __( 'Top Menu' ) );
}

The heavy lifting is done, now we need to address the actual display of the menu. Let’s open the header.php template file and place the custom function appropriately.

<div id="centeredmenu">
	<?php custom_nav_menu(); ?>
</div> <!-- #centeredmenu -->

Now for all intent and purpose the CSS from Matthew James Taylor’s post can be dropped into the style.css file, like so:

/* Main menu settings */
#centeredmenu {
   clear:both;
   float:left;
   margin:0;
   padding:0;
   border-bottom:1px solid #000; /* black line below menu */
   width:100%;
   font-family:Verdana, Geneva, sans-serif; /* Menu font */
   font-size:90%; /* Menu text size */
   z-index:1000; /* This makes the dropdown menus appear above the page content below */
   position:relative;
}

/* Top menu items */
#centeredmenu ul {
   margin:0;
   padding:0;
   list-style:none;
   float:right;
   position:relative;
   right:50%;
}
#centeredmenu ul li {
   margin:0 0 0 1px;
   padding:0;
   float:left;
   position:relative;
   left:50%;
   top:1px;
}
#centeredmenu ul li a {
   display:block;
   margin:0;
   padding:.6em .5em .4em;
   font-size:1em;
   line-height:1em;
   background:#ddd;
   text-decoration:none;
   color:#444;
   font-weight:bold;
   border-bottom:1px solid #000;
}
#centeredmenu ul li.active a {
   color:#fff;
   background:#000;
}
#centeredmenu ul li a:hover {
   background:#36f; /* Top menu items background colour */
   color:#fff;
   border-bottom:1px solid #03f;
}
#centeredmenu ul li:hover a,
#centeredmenu ul li.hover a { /* This line is required for IE 6 and below */
   background:#36f; /* Top menu items background colour */
   color:#fff;
   border-bottom:1px solid #03f;
}

/* Submenu items */
#centeredmenu ul ul {
   display:none; /* Sub menus are hiden by default */
   position:absolute;
   top:2em;
   left:0;
   right:auto; /*resets the right:50% on the parent ul */
   width:10em; /* width of the drop-down menus */
}
#centeredmenu ul ul li {
   left:auto;  /*resets the left:50% on the parent li */
   margin:0; /* Reset the 1px margin from the top menu */
   clear:left;
   width:100%;
}
#centeredmenu ul ul li a,
#centeredmenu ul li.active li a,
#centeredmenu ul li:hover ul li a,
#centeredmenu ul li.hover ul li a { /* This line is required for IE 6 and below */
   font-size:.8em;
   font-weight:normal; /* resets the bold set for the top level menu items */
   background:#eee;
   color:#444;
   line-height:1.4em; /* overwrite line-height value from top menu */
   border-bottom:1px solid #ddd; /* sub menu item horizontal lines */
}
#centeredmenu ul ul li a:hover,
#centeredmenu ul li.active ul li a:hover,
#centeredmenu ul li:hover ul li a:hover,
#centeredmenu ul li.hover ul li a:hover { /* This line is required for IE 6 and below */
   background:#36f; /* Sub menu items background colour */
   color:#fff;
}

/* Flip the last submenu so it stays within the page */
#centeredmenu ul ul.last {
   left:auto; /* reset left:0; value */
   right:0; /* Set right value instead */
}

/* Make the sub menus appear on hover */
#centeredmenu ul li:hover ul,
#centeredmenu ul li.hover ul { /* This line is required for IE 6 and below */
   display:block; /* Show the sub menus */
}

Although this will work as is in most cases there are a few items that can be modified to better suit a theme. On the next page is the actual CSS being used in the Shades theme, version 1.6, to accommodate its requirements as well as meeting current theme review criteria as noted on the WordPress codex page here.

What May Need To Be Adjusted

Note the changes at the following lines: 231, 251, 254, 259, 262, 296, and especially 310 for multiple line menus.

/* Main menu settings */
#centeredmenu {
   clear:both;
   float:left;
   margin:0;
   padding:0;
   border-bottom:1px solid #000; /* black line below menu */
   width:100%;
   font-family:Verdana, Geneva, sans-serif; /* Menu font */
   font-size:90%; /* Menu text size */
   z-index:1000; /* This makes the dropdown menus appear above the page content below */
   position:relative;
}

/* Top menu items */
#centeredmenu ul {
   margin:0;
   padding:0;
   list-style:none;
   float:right;
   position:relative;
   right:50%;
}
#centeredmenu ul li {
   margin:0 0 0 1px;
   padding:0;
   float:left;
   position:relative;
   left:50%;
   /* top:1px; */
}
#centeredmenu ul li a {
   display:block;
   margin:0;
   padding:.6em .5em .4em;
   font-size:1em;
   line-height:1em;
   background:#ddd;
   text-decoration:none;
   color:#444;
   font-weight:bold;
   border-bottom:1px solid #000;
}
#centeredmenu ul li.active a {
   color:#fff;
   background:#000;
}
#centeredmenu ul li a:hover {
   /* background:#36f; /* Top menu items background colour */
   background: #8c8c8c;
   color:#fff;
   /* border-bottom:1px solid #03f; */
   border-bottom:1px solid #444;
}
#centeredmenu ul li:hover a,
#centeredmenu ul li.hover a { /* This line is required for IE 6 and below */
   /* background:#36f; /* Top menu items background colour */
   background: #8c8c8c;
   color:#fff;
   /* border-bottom:1px solid #03f; */
   border-bottom:1px solid #444;
}

/* Submenu items */
#centeredmenu ul ul {
   display:none; /* Sub menus are hiden by default */
   position:absolute;
   top:2em;
   left:0;
   right:auto; /*resets the right:50% on the parent ul */
   width:10em; /* width of the drop-down menus */
}
#centeredmenu ul ul li {
   left:auto;  /*resets the left:50% on the parent li */
   margin:0; /* Reset the 1px margin from the top menu */
   clear:left;
   width:100%;
}
#centeredmenu ul ul li a,
#centeredmenu ul li.active li a,
#centeredmenu ul li:hover ul li a,
#centeredmenu ul li.hover ul li a { /* This line is required for IE 6 and below */
   font-size:.8em;
   font-weight:normal; /* resets the bold set for the top level menu items */
   background:#eee;
   color:#444;
   line-height:1.4em; /* overwrite line-height value from top menu */
   border-bottom:1px solid #ddd; /* sub menu item horizontal lines */
}
#centeredmenu ul ul li a:hover,
#centeredmenu ul li.active ul li a:hover,
#centeredmenu ul li:hover ul li a:hover,
#centeredmenu ul li.hover ul li a:hover { /* This line is required for IE 6 and below */
   /* background:#36f; /* Sub menu items background colour */
   background: #8c8c8c;
   color:#fff;
}

/* Flip the last submenu so it stays within the page */
#centeredmenu ul ul.last {
   left:auto; /* reset left:0; value */
   right:0; /* Set right value instead */
}

/* Make the sub menus appear on hover */
#centeredmenu ul li:hover ul,
#centeredmenu ul li.hover ul { /* This line is required for IE 6 and below */
   display:block; /* Show the sub menus */
   z-index: 1500; /* Required for multi-line menus */
}

/* -- Extra Window Dressings -- */
#centeredmenu ul li a {
  /* optional rounded corners for browsers that support it */
  -moz-border-radius: 5px 5px 0 0;
  -khtml-border-radius: 5px 5px 0 0;
  -webkit-border-radius: 5px 5px 0 0;
  border-radius: 5px 5px 0 0;
}

#centeredmenu ul li:first-child a { /* First parent menu item */
  /* optional rounded corners for browsers that support it */
  -moz-border-radius: 10px 5px 0 0;
  -khtml-border-radius: 10px 5px 0 0;
  -webkit-border-radius: 10px 5px 0 0;
  border-radius: 10px 5px 0 0;
}

#centeredmenu ul li:last-child a { /* Last parent menu item */
  /* optional rounded corners for browsers that support it */
  -moz-border-radius: 5px 10px 0 0;
  -khtml-border-radius: 5px 10px 0 0;
  -webkit-border-radius: 5px 10px 0 0;
  border-radius: 5px 10px 0 0;
}

#centeredmenu ul ul li:last-child a { /* remove rounded corners from sub-menu items */
  /* optional rounded corners for browsers that support it */
  -moz-border-radius: 0;
  -khtml-border-radius: 0;
  -webkit-border-radius: 0;
  border-radius: 0;
}

#centeredmenu ul ul ul li a { /* "grandchild" sub-menu items */
  padding-left: 10px;
}

A little extra was added at the end of the CSS to add some rounded corner emphasis to the top menu tabs as well as some additional padding for sub-sub-menu items.

Thanks again to Mathew James Taylor for the great CSS.

Enjoy!