WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

So I'm adding descriptions to my site's main menus. Checked the box, added the text. Dropped in a custom walker in functions.php. Dropped in a wp_nav_menu call in header.php to call the custom walker. Added text to the descriptions.

All good... but then I decided I wanted to add breaks via HTML... Dammit they're being stripped out. Oh, right, I need to turn off that filter. So I do, via the correct line in functions.php. ONly, it doesn't work. The HTML is still being stripped.

Before I go on, here's the walker I'm using with the filter removal line after it:

#new walker to enable description text under menu items. 
    class description_walker extends Walker_Nav_Menu
      function start_el(&$output, $item, $depth, $args)
           global $wp_query;
           $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';

           $class_names = $value = '';

           $classes = empty( $item->classes ) ? array() : (array) $item->classes;

           $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item ) );
           $class_names = ' class="'. esc_attr( $class_names ) . '"';

           $output .= $indent . '<li id="menu-item-'. $item->ID . '"' . $value . $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        ) .'"' : '';

           $description  = ! empty( $item->description ) ? '<p class="menu_description">'.esc_attr( $item->description ).'</p>' : '';

           if($depth != 0)
                     $description = $append = $prepend = "";

            $item_output = $args->before;
            $item_output .= '<a'. $attributes .'>';
            $item_output .= $args->link_before .$prepend.apply_filters( 'the_title', $item->title, $item->ID ).$append;
            $item_output .= $description.$args->link_after;
            $item_output .= '</a>';
            $item_output .= $args->after;

            $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );

## Function to stop HTML removal from menu descriptions
    remove_filter('nav_menu_description', 'strip_tags');

More info: The HTML is recorded in the database, so it's present there... just not on output. This is in Wordpress 3.3. For clarity, here's the code that calls the menu in header.php:

            wp_nav_menu( array(
                'theme_location' => 'primary',
                'depth' => 0,
                'walker' => new description_walker())

I have that sinking feeling I'm missing something basic and just need a new pair of eyes on this... any ideas?

share|improve this question
You're resetting the description variable inside the $depth != 0 conditional block. – t31os Dec 13 '11 at 21:51
Hmmm except that depth was set to zero. Removed that code anyway and no luck. I'll add the wp_nav_menu call above for clarity. – rick gregory Dec 13 '11 at 22:32
So what do you get in the output, everything minus the HTML, or are you still seeing content from inside HTML tags? Can you provide some sample data, ie. a sample of something in the DB and a sample of what you're getting on output. – t31os Dec 13 '11 at 23:25
Sure. IN the database the description text is just a test so it looks like this: <p>Line 1</p> <p>Line 2</p> <p>Line3</p> in the generated code I get: Line 1 Line 2 Line3 just as you'd expect if the strip_tags filter was active. Since I added a remove_filter call in function.php, it shouldn't be. Same thing happens with <br /> tags. – rick gregory Dec 14 '11 at 0:03
Removed my last 2 comments, see answer. – t31os Dec 14 '11 at 0:42

in a new wordpress version, the remove_filter isn't enough, cause the desc is stripped hardcoded from post_content ...

this will do the trick:

remove_filter('nav_menu_description', 'strip_tags');
add_filter( 'wp_setup_nav_menu_item', 'cus_wp_setup_nav_menu_item' );
function cus_wp_setup_nav_menu_item($menu_item) {
                $menu_item->description = apply_filters( 'nav_menu_description',  $menu_item->post_content );
                return $menu_item;
share|improve this answer
For me this returns the content of the page, any way to fix this? – dingo_d Oct 3 '14 at 11:54

The problem is not the DB doesn't contain the HTML, the filter seems to work at getting the information saved, the issue is that the menu administration page strips HTML, it's written into the walker that displays that page.

Take a look at line 167 here.

HTML is escaped when it's displayed, because naturally it's not suppose to support HTML, i'm not sure where that occurs exactly when displaying the nav menu frontside, but doing a little debugging and dumping of the $item variable lead to a discovery.

$item->post_content will hold the description, but with the HTML!!... use that in place of $item->description and you should get the result you're after.. ;)

Hope that helps.. :)

share|improve this answer
Ah nice... It's now outputting the html tags as text, but I can solve that I think. Thanks! Oddly, this still feels broken to me. The description call SHOULD work. It's referenced in several places on the WP support site and the codex entry for custom walkers points to a walker like my original one (wordpress.stackexchange.com/questions/14037/…). However, your way gets me what I want, so again, THANKS. – rick gregory Dec 14 '11 at 0:55
Yeah i wasn't in the mood to keep digging(i understand what you're saying), there must be another function or method the data passes through before it reaches the walker(or something), but the workaround does work just fine and i've already had my share of digging through menu code today, lol.. – t31os Dec 14 '11 at 1:07

Your Answer


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.