post

How to Add Menu Descriptions & Featured Images to WordPress Menu Items

Recently I read an awesome post by Bill Erickson about customizing WordPress menus. However, there are two things I wanted this class to do that in its original form it doesn’t do.

So since out of the box, WordPress doesn’t intuitively allow you to add descriptions to the menu without requiring some custom code, rather the Walker class extended.

Since Bill has done an excellent job at this I will extend his code to add the options of having a featured image and/or descriptions applied based on depth.

Add this to your functions.php file.

[php]<?php
class Menu_With_Description 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 ) .’"’ : ”;

// get user defined attributes for thumbnail images
$attr_defaults = array( ‘class’ => ‘nav_thumb’ , ‘alt’ => esc_attr( $item->attr_title ) , ‘title’ => esc_attr( $item->attr_title ) );
$attr = isset( $args->thumbnail_attr ) ? $args->thumbnail_attr : ”;
$attr = wp_parse_args( $attr , $attr_defaults );

$item_output = $args->before;

// thumbnail image output
$item_output .= ( isset( $args->thumbnail_link ) && $args->thumbnail_link ) ? ‘<a’ . $attributes . ‘>’ : ”;
$item_output .= apply_filters( ‘menu_item_thumbnail’ , ( isset( $args->thumbnail ) && $args->thumbnail ) ? get_the_post_thumbnail( $item->object_id , ( isset( $args->thumbnail_size ) ) ? $args->thumbnail_size : ‘thumbnail’ , $attr ) : ” , $item , $args , $depth );
$item_output .= ( isset( $args->thumbnail_link ) && $args->thumbnail_link ) ? ‘</a>’ : ”;

// menu link output
$item_output .= ‘<a’. $attributes .’>';
$item_output .= $args->link_before . apply_filters( ‘the_title’, $item->title, $item->ID ) . $args->link_after;

// menu description output based on depth
$item_output .= ( $args->desc_depth >= $depth ) ? ‘<br /><span class="sub">’ . $item->description . ‘</span>’ : ”;

// close menu link anchor
$item_output .= ‘</a>';
$item_output .= $args->after;

$output .= apply_filters( ‘walker_nav_menu_start_el’, $item_output, $item, $depth, $args );
}
}
[/php]

All Menus

To highjack ALL of your menus, enter this code in your functions.php.
[php]<?php
add_filter( ‘wp_nav_menu_args’ , ‘my_add_menu_descriptions’ );
function my_add_menu_descriptions( $args ) {
$args['walker'] = new Menu_With_Description;
$args['desc_depth'] = 0;
$args['thumbnail'] = true;
$args['thumbnail_link'] = false;
$args['thumbnail_size'] = ‘nav_thumb';
$args['thumbnail_attr'] = array( ‘class’ => ‘nav_thumb my_thumb’ , ‘alt’ => ‘test’ , ‘title’ => ‘test’ );

return $args;
}[/php]

Menus Based on Location

To highjack a menu based on registered and assigned location, then use this code in your functions.php.
[php]<?php
add_filter( ‘wp_nav_menu_args’ , ‘my_add_menu_descriptions’ );
function my_add_menu_descriptions( $args ) {
if ( $args['theme_location'] == ‘primary’ ) {
$args['walker'] = new Menu_With_Description;
$args['desc_depth'] = 0;
$args['thumbnail'] = true;
$args['thumbnail_link'] = false;
$args['thumbnail_size'] = ‘nav_thumb';
$args['thumbnail_attr'] = array( ‘class’ => ‘nav_thumb my_thumb’ , ‘alt’ => ‘test’ , ‘title’ => ‘test’ );
}

return $args;
}[/php]

Menus via WordPress Custom Menu Widget

To highjack a custom menu based menu id that is called using the custom menu widget, or even a manual method (if the menu is being called by a location, you must use ‘theme_location’), then use this code in your functions.php. This will highjack any menu called by the custom menu widget assuming you only have the standard registered theme locations. The example below assumes a standard theme custom menu registered locations for Genesis. Change ‘primary’ and/or ‘secondary’ to whatever your theme adds and add whatever more menus that your theme has to only target the custom menu widget.
[php]<?php
add_filter( ‘wp_nav_menu_args’ , ‘my_add_menu_descriptions’ );
function my_add_menu_descriptions( $args ) {
if ( ( $args['theme_location'] != ‘primary’ ) && ( $args['theme_location'] != ‘secondary’ ) ) {
$args['walker'] = new Menu_With_Description;
$args['desc_depth'] = 0;
$args['thumbnail'] = true;
$args['thumbnail_link'] = false;
$args['thumbnail_size'] = ‘nav_thumb';
$args['thumbnail_attr'] = array( ‘class’ => ‘nav_thumb my_thumb’ , ‘alt’ => ‘test’ , ‘title’ => ‘test’ );
}

return $args;
}[/php]

There is a caveat though. There are certain menu items that may not have a featured image such as custom links, categories, etc. There is a possible work-around that I am trying to work out.

Here is the result of a sandbox description and featured images for all types (not just pages and posts), which I will be posting soon or writing up into a plugin…

Sandbox Genesis Menu with Descriptions and Featured Images

About Travis Smith

As a WordPress Enthusiast, Travis writes about his journey in WordPress trying to help other WordPress travelers and enthusiasts with tutorials, explanations, & demonstrations of the things he learns.

Comments

  1. Thank your for this code and tutorial! With that I finally got menu descriptions working in Genesis – and finally for primary and secondary menu! Absolutely awesome! All works correctly: linking, styling, thumbnail…!

    The only thing which was not working was a custom menu in the sidebar via core WP widget. Don’t know why but the other things matter more to me. So thanks again!

    Suggestion: would make for a perfect Genesis plugin – to have options like thumbnail size, css class, linking for image in the backend! But for developers your above solution is still a perfect way!

    Servus, Dave :)

    • Hello David,

      For this to be made into a plugin, there is still a lot of work that needs to be done. Since writing this post, I have redone how the featured images (post thumbnails) are done, which I still have one more step. Then I would have to develop an options page. What options would you like to see?

      Thanks,

    • Hello David,

      I figured out the error and made the appropriate adjustments to the post.

      Thanks,

  2. I read Bill’s tutorial and yours above. They are awesome, and thank you!

    However, I think there’s just one thing missing from each…an example of the end result. Do you have any examples you can point us to?

    • Hello Adam,

      Both Bill and myself are working these into sites that are currently in development. He included a screen shot of his, but I have not (lack permission due to NDA). I do it in a sandbox of the next version of this code. Better yet, someone else may send me an image with an example!

      Thanks,

  3. Fantastic article and code!

    This is very useful, and I want to thank you for sharing it.

    +1 to the Genesis plugin idea. That would be quite popular I would think.

  4. Awesome! , but there doesn’t appear to be any way to control the thumbnail size. Scratch my previous comment – I worked it out. Stupid mistake really – I didn’t notice thumbnail arg was nav_thumb, whereas I had used nav-thumb.

    Cheers.

  5. Hi Travis, thanks for this tutorial! I used it once and got it to work, but the client ended up choosing a different kind of menu after all.

  6. How would I dynamically get the thumbnail alt and title tags? I want to use the title the menu link is pointing to and the excerpt as the alt tag. Or at the very least repeat the menu item title as the alt tag.

    Any thoughts?

  7. Did this ever become a plugin?
    Most all of my menu items are custom links linking to custom post-types so there is no capability to add a featured image to each of the links.
    Hoping this project is still alive as it seems to be quite far along

  8. I am trying to replicate something like this menu:
    http://awesomescreenshot.com/0e0dlfx7d

    basically each link is a link to the custom post-type ‘travel, cruise, etc’…

  9. Hi Travis, Ignore my last message. All fixed now. Human typo error regarding the menu names.
    Excellent code – thanks.
    Chris

  10. Great code. Thanks. Is there a way somehow to output “no thumbnail” if no thumbnail exists or to output a taxonomy category thumbnail if the menu item is linked to a taxonomy category?

  11. Thanks!
    I was looking for this code. It works great.

  12. Thank you so much, it worked great!
    Just a beginner question : how can I put the link to the page on the thumbnail ?
    (if it is possible)

  13. Hello!
    I used your code and thank you very much. I have a question I hope you can help me.
    I would like that, if there is a thumbnail defined for the article, only the thumbnail appears in the menu (and no title nor description.)
    is that possible and could you tell me how ? thank you so much!
    f

  14. Fantastic post!

    I should note though, I was getting a “>” (close bracket) before each menu item. Not sure why but removing the LI tag did the trick and removed the rogue bracket (I ended up replacing the LI tag with an ARTICLE tag which worked out as I designed the initial HTML template as such. I added a closing ARTICLE tag of course). Anyone else run into this?

    Cheers!

  15. Thank you very much! It works perfectly!

Leave a Reply

%d bloggers like this: