wp_nav_menu add <span></span> tags inside <a></a> tags that is parent

I found examples adding a class to top level items, so we can display an arrow in menu items with sub-items, but is seems terrible to cope with the already built in WordPress classes, can’t display the arrow with current and CSS hover, it just ruins all states.

The current nav menu is like this <li><a>Text</a></li>

Read More

Is there someway to add a <span class="arrow"></span> within the parent <a></a> tags instead?!

Add -> “<span class="arrow"></span>” -> inside <a/></a> tags

Thus -> <li><a>Text<span class="arrow"></span></li></a> that is parent.

the current code Adds the <span></span> tags outside the <a></a> tags

class My_Walker_Nav_Menu extends Walker_Nav_Menu {
    function start_lvl(&$output, $depth, $args) {
        $indent = str_repeat("t", $depth);
        if('primary' == $args->theme_location && $depth ==0){
            $output .='<span class="arrow"></span>';
        }
        $output .= "n$indent<ul class="sub-menu">n";
    }
}

Related posts

Leave a Reply

1 comment

  1. You are overwriting the incorrect method. You need the start_el instead. Here is the code for it:

    class add_span_walker extends Walker_Nav_Menu {
        function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
            global $wp_query;
            $indent = ( $depth ) ? str_repeat( "t", $depth ) : '';
    
            $class_names = '';
    
            $classes = empty( $item->classes ) ? array() : (array) $item->classes;
            $classes[] = 'menu-item-' . $item->ID;
    
            $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
            $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
    
            $id = apply_filters( 'nav_menu_item_id', 'menu-item-'. $item->ID, $item, $args );
            $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
    
            $output .= $indent . '<li' . $id . $class_names .'>';
    
            $attributes  = ! empty( $item->attr_title ) ? ' title="'  . esc_attr( $item->attr_title ) .'"' : '';
            $attributes .= ! empty( $item->target )     ? ' target="' . esc_attr( $item->target     ) .'"' : '';
            $attributes .= ! empty( $item->xfn )        ? ' rel="'    . esc_attr( $item->xfn        ) .'"' : '';
            $attributes .= ! empty( $item->url )        ? ' href="'   . esc_attr( $item->url        ) .'"' : '';
    
            $item_output = $args->before;
            $item_output .= '<a'. $attributes .'>';
            $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
    
            if ( 'primary' == $args->theme_location ) {
                $submenus = 0 == $depth || 1 == $depth ? get_posts( array( 'post_type' => 'nav_menu_item', 'numberposts' => 1, 'meta_query' => array( array( 'key' => '_menu_item_menu_item_parent', 'value' => $item->ID, 'fields' => 'ids' ) ) ) ) : false;
                $item_output .= ! empty( $submenus ) ? ( 0 == $depth ? '<span class="arrow"></span>' : '<span class="sub-arrow"></span>' ) : '';
            }
            $item_output .= '</a>';
            $item_output .= $args->after;
    
            $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
        }
    }
    

    This code will add a <span class="sub-arrow"></span> to top-level menu items from the menu selected for the primary theme location in case that this menu item has any child items.