I have a problem with my theme...

I use Agama, and i've checkmarked "description" in the menu settings, but it won't display it on the frontend, since the theme doesn't allow it.

But then I found this function:

function prefix_nav_description( $item_output, $item, $depth, $args ) {
if ( !empty( $item->description ) ) {
    $item_output = str_replace( $args->link_after . '</a>', '<span class="menu-item-description">' . $item->description . '</span>' . $args->link_after . '</a>', $item_output );
return $item_output;
add_filter( 'walker_nav_menu_start_el', 'prefix_nav_description', 10, 4 );

That helped me get the description to be shown. But i can't make line-breaks in my description. Everytime I just make a line-break or inserts
and save the changes, it removes the changes again.

So can anyone help me with a function that both makes the description be showned and also makes it possible for me to add
in the description.

Thanks :D

  • It's really strange. I'm testing this and the description gets saved to the database with a line break, but when it's output into the textarea again for editing the line break is removed, so it will get saved without a linebreak the next time its saved. As far as I can tell this textarea is escaped with esc_html() but in my testing I can't get esc_html() to remove line breaks, so I don't know why they're removed here. Mar 14 '18 at 14:41

OK, it took me a little while to debug this behaviour, but... Everything is clear for me right now... I'm not sure if this is fully intentional...

Why is it so?

So... The line breaks are stored in DB correctly. Then in wp_setup_nav_menu_item the description field is filled based on post_content column of given menu item post.

On line 845 (https://core.trac.wordpress.org/browser/tags/4.9/src/wp-includes/nav-menu.php#L845) it is shortened and filtered:

if ( ! isset( $menu_item->description ) ) {
     * Filters a navigation menu item's description.
     * @since 3.0.0
     * @param string $description The menu item description.
    $menu_item->description = apply_filters( 'nav_menu_description', wp_trim_words( $menu_item->post_content, 200 ) );

And the wp_trim_words function trims text to a certain number of words, but it doesn't preserve line breaks - so any line break is replaced with space.

So what can we do about it?

There are no filters in wp_trim_words that will allow us to modify its behaviour. There is also no filters that will allow us to skip wp_trim_words call, but...

You can replace the \n with some placeholder and then use nav_menu_description filter to replace it back. There even is no need that users put this placeholder himself - we can replace them with a placeholder with save_post filter:

function replace_nl_placeholder_nav_menu_description( $description ) {
    return str_replace('%NL% ', "\n", $description);
add_filter('nav_menu_description', 'replace_nl_placeholder_nav_menu_description');

function replace_nl_with_placeholder_nav_menu_description( $post_id ) {
    if ( 'nav_menu_item' !== get_post_type($post_id) ) return;

    remove_action( 'save_post', 'replace_nl_with_placeholder_nav_menu_description' );

    wp_update_post( array(
        'ID' => $post_id,
        'post_content' => str_replace("\n", '%NL% ', get_post_field('post_content', $post_id, 'raw'))
    ) );

    add_action( 'save_post', 'replace_nl_with_placeholder_nav_menu_description' );
add_action( 'save_post', 'replace_nl_with_placeholder_nav_menu_description' );

And that's all. You only have to remember to properly display such line breaks in your theme (nl2br and so on).

  • Oh man, what an obnoxious filter nav_menu_description is! It doesn't even pass through the menu item object. Mar 15 '18 at 15:58
  • @JacobPeattie I guess no one ever used it ;) Mar 15 '18 at 18:43
  • 1
    Nice digging. Since I am already using ACF on the website I ran into this problem with, I decided to use an ACF field assigned to menu items with a description box of my own. Sharing here in case anyone is in a similar boat.
    – Matt Keys
    Jan 5 '19 at 22:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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