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. Oct 26, 2011 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, 2011 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. Oct 26, 2011 at 9:55

1 Answer 1


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 and acknowledge that you have read and understand our privacy policy and code of conduct.

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