Customizing WordPress Menus

Over the past few days I’ve had a few people ask me some specific questions on customizing menus. Since none of them are long enough to justify a full post, I thought I’d make one post with all the tips.

Using Menu Descriptions

The menu and descriptions are powered by a WordPress Menu

From the Menus screen, click on Screen Options in the top right and check “Description”. You can now write a description for any of your links. Unfortunately these descriptions can’t be displayed without writing some custom code. We’ll need to create what’s called a walker class.

Place this in your functions.php file:

We’re basically creating the markup for the menu. The key here is the line with this: $item->description

That adds the description to the link, wrapped in a .sub class.

Now all you’ll need to do is include the walker in your wp_nav_menu() arguments.

Showing certain pages to logged in users

One of the most powerful features of WordPress menus is Classes. From the Appearance > Menus screen, click Screen Options in the top right corner and check Classes. You’ll now be able to add custom classes to any menu item.

For this specific technique, add the class “logged-in-nav” to the menu items you want visible only to logged in users. Then, add the following CSS to your stylesheet.

In Genesis (and probably other themes), when a user is logged in it adds the body class “logged-in”. If your theme doesn’t have this already, you can use the body class filter to add it.

Adding Extra Code to the Menu

As described at the end of my last post on Theme Settings, there are some useful filters for modifying the output of menus.

There’s two filters that you can use, depending on how much you know about the menu.

wp_nav_menu_items – runs on all menus
wp_nav_menu_{menu-name}_items – only runs on that specific menu (ex: wp_nav_menu_primary_items if the menu is named Primary).

There are two parameters for each filter, $menu and $args. The $menu object contains the actual menu. If you need to modify the actual content of the menu, you’ll need to modify this object (ex: using preg_replace to add or change classes on certain menu items). A lot of times I won’t need to modify the actual content, I’ll just want to stick something on the end. In that case I’ll do something like this:

That will add extra code to the end of the menu (I’m returning the original menu intact, as well as my addition, $extras.

The other parameter, $args, contains information about the menu. For instance, let’s say we want to add something to the end of the Secondary menu in Genesis. Since we’re using a theme location, the menu could have any name (so we can’t use the second filter). We’ll use the first and use the $args to figure out if we’re on the secondary menu.

genesis intermediate menu wordpress

Receive New Posts by Email


  1. Hi Bill,
    Great tip. I think there is a typo on line 2?
    Should be:
    function be_menu_extras($menu, $args) {

    1. Good catch. I created this by combining code from a lot of projects and tried renaming all of the functions to use the same name, but this one slipped through. I’ve updated the code.

  2. Thanks for the tuts! Regarding “Adding Extra Code to the Menu”, I’m trying to do this but I want to add a second wrapper. Any ideas?

    /*WordPress generates this code*/

    /* I want this code generated. I want to add the .nav-holder wrapper */

    Do I have to use a nav walker for this or can I use a filter?

    Thanks in advance:)

  3. Thanks for the info on the classes and menu items, I had never thought of that, but was always plagued with how to only show menu items to logged in users.

    Only one small change, don’t use the default menu #nav, as I’ve created a custom menu, maybe highlight that whatever name you give the menu under the menu name (I called mine MainMenu), then simply substitute the #nav -> #menu-MainMenu

    It did only take me a few minutes to find the problem, but I think if I used the default menu structure, then this would have worked. Anyway, great piece of code, simple, and (if you don’t mind) I’m going to create a post about this and link back to you.


  4. Hey Bill,

    Is there a way to implement this into Genesis so that I can display the Description (Subtitle) In my Sub Nav Categories?

      1. Hey Bill Merry Christmas!

        I have got it taken care of and here is the code in case anyone else finds worth in this.

        This is for the genesis functions.php

        [PHP]/** Add description to secondary navigation */
        add_filter( ‘walker_nav_menu_start_el’, ‘add_description’, 10, 4 );
        function add_description( $item_output, $item, $depth, $args ) {

        $args = (array) $args;

        if ( $args[‘theme_location’] != ‘primary’ ) {
        return preg_replace( ‘/([^<]*?)</', '$1' . "{$item->post_content}<", $item_output );
        else {
        return $item_output;


        Here is the .CSS

        [CODE].menu-description {
        clear: both;
        color: inherit;
        display: block;
        font-family: Arial,Helvetica,sans-serif;
        font-size: 12px;
        font-style: normal;
        font-weight: 400;
        line-height: 3px;
        text-transform: none;
        margin-bottom: 6px;

        Here is what it looks like in action

        I have a question though Bill perhaps you can pop in to my site and tell me how to get the subnav line divider images to regulate where it begins and ends with the image. I cannot figure it out.
        Veteran coder I am not!

        Merry Christmas Brother!


        1. I’m sorry but I’m not exactly sure what you’re asking. The line dividers in the nav seem to be working just fine to me.

          1. I think I have it worked out with the exception that when I hove over the Home Category in my Navbar the Nav Line divider image disappears. Can you offer some insight into this bill?

            Thank you Bill


        2. Campbell,

          Take a look at line 609 of style.css. You have a CSS rule for #subnav li a:hover that is changing your background color on hover.

          1. Hi John

            I had actually tried that last night and it was not the cause of the problem. If you notice, if that was the root of the problem it would duplicate it on every category that was hovered. The problem is that it is an abnormality that only manifests on the Home Category and no other. I am quite baffled by the situation and tried for hours to figure out how to correct it with no success I might add.

        3. I think that line is the root of your problem. The background color is overriding the background for the ul on 589. When you hover over the li a, its changing the background color and masking the transparency on the ul color background (if you follow me)

  5. Hi Bill I was wondering if this could be changed a bit to prevent some menu items from being seen by logged in users. I would like the logged in user to only see the new menu items and not the regular menu items that the public sees.


  6. Hi Bill,

    Thanks for your post. I’ve played around with a plugin that is suppose to do the same CSS try for hiding menu options. I updated my styles.CSS file for the active theme and changed the the CSS to logged-in-nav for the item that I wanted to hide in my bar. However, I have be unable to get this working. This is a custom menu that I created and I’m using the Nova Theme. Do you think it could be a problem with my theme or something? We would surely appreciate your advise.


    1. View the source of your page and make sure the body classes and menu classes are showing up. Use a tool like Inspector for Chrome or Firebug for Firefox to see what’s going on with the CSS.

  7. Hi, I think I may be lost a little but when i do
    function be_menu_extras($menu, $args) {
    echo ‘test test test’;
    add_filter(‘wp_nav_menu_primary_items’,’be_menu_extras’, 10, 2);

    nothing happen, any help would be great please…

    1. You need to have a menu called “Primary”. The filter is ‘wp_nav_menu_{menu_slug}_items’.

      So if you have a menu called “Primary Menu”, you would use a filter called ‘wp_nav_menu_primary_menu_items’.

      Personally I don’t like using this approach because it depends upon what the menu is named in the backend. If a user renames the menu, your code doesn’t apply. A better approach is to use the ‘wp_nav_menu_items’ filter and check to see the theme location. The code you write doesn’t necessarily only apply to a menu called “Primary”, but you want it to apply to any menu that shows up in the “Primary Menu” theme location.

  8. Thanks for the menu description instructions Bill.

    My theme seems to use a plugin in it’s framework called “Dropdown Menus” (unless this is something all themes use now), that uses a dropdown_menu function… so for the life of me, i’ve searched the whole theme, I can’t find where they define the wp_nav_menu().

    In fact, the beginning of the dropdown_menu page says to return false if wp_nav_menu exists.

    Any ideas what this means? Where would I include the walker if I don’t have a definition of wp_nav_menu?


  9. Hi Bill, thanks for the post. I came across when looking to implement a nav walker into my genesis child theme. I am still planning my theme rather than jumping in as genesis is still very new to me. I’ve spent the last three months making sure I’m practised with wordpress and php before I delve into the framework. Is adding a nav walker in a genesis child theme a similar process to a regular wordpress theme?

    1. If you’re adding a walker to a custom menu you create, then it’s exactly the same as in any other WordPress theme. Ex:

      If you’re adding it to one of the menus Genesis provides (Primary and Secondary menus), it’s a little more difficult. I haven’t tried it before but I believe you could use the ‘wp_nav_menu_args’ filter and check if ‘primary’ or ‘secondary’ is the theme location. See:

      You could also unhook the function that adds the menu and create your own:

      I’m writing a tutorial right now that goes in more details. It took some digging to find that filter, so want to help others find it too.

      1. Bill, thank you so much for the in depth reply. I’m going to go into the process now myself and will report back on how it goes.

        I look forward to reading the tutorial 🙂

        Thanks again

        1. Hi Bill, I’ve read your tutorial and developed in theory the code I wish to implement into my genesis theme. Using wp_nav_menu_args is perfect for adding my menu css class. I’m also adding a separate walker for the mobile menu that can be checked in the admin to display the same menu but in the mobile format. To achieve the menu style I’m aiming for I want to add additional body wraps to the genesis header and footer, I also want to add my new nav walker with custom wrapping divs which I can do using the example code you provided with some additions and the last thing being I want to wrap the genesis primary nav in further custom wrappers.

          So far I’m studying genesis/lib/structure/header.php
          Here’s what I think I should do.

          Add body wraps by hooking into the genesis_before_header

          Add my new walker by also including it in genesis_before-header

          Here’s where I start to think am I going to far? i’m going to want to pull in genesis_title on both menu’s.

          Any advise or point in the right directions for these types of edits or further study? I’m extremely enthusiastic about learning to code and I really want to push through the genesis learning curve so anything you can advise is going to be greatly appreciated.

          Thanks again

  10. Dear Bill

    I am currently using the Executive Pro theme. My site’s main navigation is a custom menu in the Header Right widget.

    I would like to have different primary and secondary menus for different pages. Thus, depending on which menu item is selected in the custom menu in the Header Right widget, a specific primary and secondary menu will show on the relevant page. The secondary menu acts as a sticky menu – its menu items is a replica of the primary menu. The secondary sticky menu appears as soon as you scroll down the page.

    It seems that I can only have 1 menu allocated to the primary and secondary menu location. I’m not sure which method is best to achieve this. I have had a look at many options, but I feel overwhelmed. This is my first genesis wordpress site.

    Any pointers would be much appreciated. Thank you.

  11. I am using your Genesis Subpages as Secondary Menu and it works great for two levels. When I had a third level it breaks my secondary menu bar. Unfortunately this isn’t online for you to look at.

    The primary menu with and without the plugin, and the secondary menu when the plug in is disabled returns:
    ul id=”menu-main-menu” class=”menu genesis-nav-menu menu-primary”
    li id=”menu-item-14″ class=”menu-item menu-item-type-post_type menu-item-object-page menu-item-14″
    ul class=”sub-menu”

    And the plugin disabled the secondary returns:
    ul id=”menu-genesis-subpages” class=”nav genesis-nav-menu”
    li class=”page_item page-item-21 page_item_has_children menu-item”
    ul class=’children’

    The top menu or secondary when plugin is disabled will drop down for the second and third levels. With the plugin enabled, the third level is always present on the secondary location, making it taller, and throws off the other menu items on spacing.

    I’ve tried css coding in the ways I can think of, I can’t find some of the classes in any css sheet though to copy it off of.

    I’ve tried editing your php but I don’t know enough to make it work that way either.

    Thanks for a nudge in the right direction

    1. I found your snippet for adding to the agency theme and that helped me start the styling. I’m still having an issue with the second level breaking the layout / nav bar.

      I tried the tertiary bar code I found that you wrote but I get an error when I add it.

      Parse error: syntax error, unexpected ‘id’ (T_STRING), expecting ‘,’ or ‘;’

      on line

      if ( !empty( $menu ) ) echo ‘’.$menu.’’;

      1. I finally hacked everything except the tertiary menu bar which I haven’t decided if I should use a third bar or just let it stay a dropdown.
        Thanks much for the code and info you put out

  12. Hi Bill,

    I’ve adding the menu description to my WordPress menu. I only want to add it to specific menu items. I could hide the ‘sub’ div on the menu items I don’t want the description on but I’d like to learn how to do it with the walker if possible.

    Could you provide any reference to this type of functionality?

  13. Hi there,

    Could you tell me what code should go in the header to call the walker please? I would like to use this to create a mega menu like Mashable.

Leave a comment