I've created a menu using wp_nav_menu in my theme using the most simple setup as possible:

wp_nav_menu( array( 'theme_location' => 'my_theme_top_menu') );

And in my functions.php:

    array('my_theme_top_menu' => 'Top Menu' )

However, I'm running into strange behaviour when the user creates a menu in wp-admin and assigns it to this menu. When you first select the theme, it defaults to the default menu built from pages, the markup looks like this:

<div class="menu">
       <li class="page_item page-item-51">
           <a href="http://www.mdunham.co.uk/bligs/">About Us</a>

But, if a user selects one of their pre-defined menus the markup that builds the menu completely changes:

 <div class="menu-main-menu-container">
    <ul id="menu-main-menu" class="menu">
           <li id="menu-item-102" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-29 current_page_item menu-item-102">
               <a href="http://www.site.co.uk/">Home</a></li>

Why is this happening? It's like when uses a defined menu WP menu it WP defaults(or settings I've defined), yet when there is no defined menu and it falls back it uses a different, bastardized set of options which I haven't actually set anywhere myself.

  • Is that the right way round? Looks like the top one is the actual menu assigned via admin and the bottom one is the wp_list_pages fallback. – sanchothefat Oct 26 '11 at 9:35
  • Ah yeah you're right, the underlying point still stands though. Are you aware of a work around for this? I am thinking a custom callback function to emulate wp_nav_menu with the default list of pages. – Dunhamzzz Oct 26 '11 at 9:49
  • To be honest I typically put in a custom callback that checks if a user is logged in with menu editing capability and show a link to the menus admin page to choose a menu. Alternatively copy the wp_list_pages() function and change the markup it generates. – sanchothefat Oct 26 '11 at 9:55

Here's the default usage of wp_nav_menu():

$defaults = array(
  'theme_location'  => ,
  'menu'            => , 
  'container'       => 'div', 
  'container_class' => 'menu-{menu slug}-container', 
  'container_id'    => ,
  'menu_class'      => 'menu', 
  'menu_id'         => ,
  'echo'            => true,
  'fallback_cb'     => 'wp_page_menu',
  'before'          => ,
  'after'           => ,
  'link_before'     => ,
  'link_after'      => ,
  'items_wrap'      => '<ul id=\"%1$s\" class=\"%2$s\">%3$s</ul>',
  'depth'           => 0,
  'walker'          => 

Notice that the default fallback for wp_nav_menu() is wp_page_menu(), for which the defaults are:

$args = array(
'sort_column' => 'menu_order, post_title',
'menu_class'  => 'menu',
'include'     => '',
'exclude'     => '',
'echo'        => true,
'show_home'   => false,
'link_before' => '',
'link_after'  => '' 

These should produce mostly the same output, with the same set of pages. However, if you need more specific control, you have a couple options:

  1. Assign a custom callback here:

    'fallback_cb' => 'mytheme_wp_nav_menu_cb'

    ...and then, define:

      function mytheme_wp_nav_menu_cb() {
          // Output whatever menu you want here

    ...so that you override wp_page_menu()

  2. Wrap your wp_nav_menu() call in a has_nav_menu() conditional:

    if ( has_nav_menu( 'my_theme_top_menu' ) ) {
        // User has applied a custom menu
        // to the my_theme_top_menu location;
        // output it
        wp_nav_menu( array( 'theme_location' => 'my_theme_top_menu') );
    } else {
        // User has NOT applied a custom menu;
        // Do something else

    ...in the else statement, you can do whatever.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.