How to use wp_nav_menu to create a select menu dropdown?

I’m using the following inside the wp_nav_menu function to create a select dropdown menu where each menu item is an option in the select dropdown…

'items_wrap' => '<select>%3$s</select>'
'before'     => '<option value="">'
'after'      => '</option>'

How do I add the link value in the 'before' declaration? Is there a better way to go about this? I know about wp_dropdown_pages, but that doesn’t work because I want users to be able to control the menu from the “Menus” page.

Related posts

Leave a Reply

3 comments

  1. You can’t do this with wp_nav_menu, because it outputs list items, and you’ll generate invalid markup with your code.

    Try using wp_get_nav_menu_items() instead.


    A quick solution for a drop down menu with a custom walker:

    class Walker_Nav_Menu_Dropdown extends Walker_Nav_Menu{
    
        // don't output children opening tag (`<ul>`)
        public function start_lvl(&$output, $depth){}
    
        // don't output children closing tag    
        public function end_lvl(&$output, $depth){}
    
        public function start_el(&$output, $item, $depth, $args){
    
          // add spacing to the title based on the current depth
          $item->title = str_repeat("&nbsp;", $depth * 4) . $item->title;
    
          // call the prototype and replace the <li> tag
          // from the generated markup...
          parent::start_el(&$output, $item, $depth, $args);
          $output = str_replace('<li', '<option', $output);
        }
    
        // replace closing </li> with the closing option tag
        public function end_el(&$output, $item, $depth){
          $output .= "</option>n";
        }
    }
    

    In your templates use it like this:

    wp_nav_menu(array(
      'theme_location' => 'primary', // your theme location here
      'walker'         => new Walker_Nav_Menu_Dropdown(),
      'items_wrap'     => '<select>%3$s</select>',
    ));
    
  2. I have found that useful:

    You can follow any responses to simplify css code dropdovn menu.

    1. Add a class parent for items that have a submenu
    2. add depth class (depth0 , depth1, depth2 …)

    add to function.php your theme

    class DD_Wolker_Menu extends Walker_Nav_Menu {
        function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ){
            $GLOBALS['dd_children'] = ( isset($children_elements[$element->ID]) )? 1:0;
            $GLOBALS['dd_depth'] = (int) $depth;
            parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
        }
    }
    add_filter('nav_menu_css_class','add_parent_css',10,2);
    function  add_parent_css($classes, $item){
         global  $dd_depth, $dd_children;
         $classes[] = 'depth'.$dd_depth;
         if($dd_children)
             $classes[] = 'parent';
        return $classes;
    }
    

    now in header.php

    wp_nav_menu( array( 'container_class' => '','container' => '',  'menu' => 'header-menu', 'walker'=> new DD_Wolker_Menu ) );
    

    header-menu replaced by the name of your menu

    CSS example code may be the

    #menu-header-menu{
        margin: 0;
        padding: 0;
    }
    #menu-header-menu  ul{
    
    }
    
    #menu-header-menu> li{
        display: inline;
        margin-left: 1.618em;
    }
    #menu-header-menu  li{
        list-style: none;
    }
    #menu-header-menu  li a{
        text-decoration: none;
        font-size:  1em;
        font-family:    'Lato',Helvetica,Arial,sans-serif ;
        letter-spacing: 1px;
    }
    #menu-header-menu li.parent::after{
        content:'+';
    }
    
    #menu-header-menu  .sub-menu {
       display: none;
       position: absolute;
       background-color: #fff;
    }
    
    #menu-header-menu  li:hover>.sub-menu{
        display: inline;
        width: auto;
        height: auto;
        border: solid 1px #BBBBBB;
        z-index: +1;
    }
    

    where #menu-header-menu – id the main UL list (you need to update that as well)