Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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>

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

Example,

Add ⇒ <span class="arrow"></span> inside ⇒ <a/></a> tags

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

The current code Adds the <span></span> tags outside the <a></a> tags that is parent

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 .='&lt;span class="arrow">&lt;/span>';
        }
        $output .= "\n$indent<ul class=\"sub-menu\">\n";
    }
}

Original question title edited from: "add span class inside <a>"

share|improve this question
    
as you want to edit the element, not the whole level, you should extend the function start_el instead of start_lvl. here you can add the <span> inside the <a>. –  fischi Nov 15 '12 at 10:11
add comment

2 Answers 2

up vote 1 down vote accepted

This actually creates two instances where it displays a span class within the tag on the primary and secondary levels so you can add different images to your span class for designing and navigating purposes.

This helps for users and developers to show if there is a drop-down to your header menu and also makes it easier to navigate within your website.

1. Add this code below to your functions.php first.

class Nav_Walker_Nav_Menu 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 );
    }
}

2. Add code below to your header.php where your wp_nav_menu is installed.

Explained below is the code so it installs the new custom menu in this case would be Nav_Walker_Nav_Menu.

<?php wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary', 'walker' => new Nav_Walker_Nav_Menu() ) ); ?>

3. Add some CSS

So it is able to show your new span arrow images within your tags in primary and secondary level.

#menu-header-menu li span.arrow { height:12px;background-image: url("images/nav-arrows.png");background-position: -8px -3px;background-repeat: no-repeat;float: right;margin: 0 0px 0 10px;text-indent: -9999px;width: 12px;}
#menu-header-menu li a:hover span.arrow{ height:12px;background-image: url("images/nav-arrows.png");background-position: -39px -3px;background-repeat: no-repeat;float: right;margin: 0 0px 0 10px;text-indent: -9999px;width: 12px;}
#menu-header-menu ul.sub-menu li span.sub-arrow { height:12px;background-image: url("images/nav-arrows.png");background-position: -8px -39px;background-repeat: no-repeat;float: right;margin: -2px 0px 0 10px;text-indent: -9999px;width: 12px;}
#menu-header-menu ul.sub-menu li a:hover span.sub-arrow{ height:12px;background-image: url("images/nav-arrows.png");background-position: -39px -39px;background-repeat: no-repeat;float: right;margin: -2px 0px 0 10px;text-indent: -9999px;width: 12px;}

hope this help! :)

share|improve this answer
add comment

Have you tried using the before or link_before parameters in your array arguments when declaring your wp_nav_menu function?

Note: use after or link_after for the opposite effect.

Example,

wp_nav_menu(

    //normal arguments here....etc

    'before'    => '<span class="arrow"></span>',

    //or 'link_before' => '<span class="arrow"></span>',


); 

From the Codex:

$before
(string) (optional) Output text before the of the link
Default: None

   e.g. 'before'    => ''

or...

$link_before
(string) (optional) Output text before the link text
Default: None

   e.g. 'link_before'    => ''

Supporting resources:

http://codex.wordpress.org/Function_Reference/wp_nav_menu

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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