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
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.
Bruce Munson says
Hi Bill,
Great tip. I think there is a typo on line 2?
Should be:
function be_menu_extras($menu, $args) {
Bill Erickson says
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.
Jamie says
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:)
Bill Erickson says
I’m sorry, WordPress strips out HTML from comments. When I leave it in comments I change the first < to & lt; (no space) You can use this filter (assuming you want it on primary nav, see above for other options) https://gist.github.com/2694251
Dave says
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.
Regards
John Russell says
Bill,
Thanks for this. It helped me figure out the first step to something I wanted to do.
Campbell says
Hey Bill,
Is there a way to implement this into Genesis so that I can display the Description (Subtitle) In my Sub Nav Categories?
Bill Erickson says
Yes it is, although it will require some work. I recommend using the ‘genesis_do_subnav’ filter to modify the subnav before it is displayed.
First you’ll need to create the walker: https://gist.github.com/1325991
Then use the walker on the subnav: https://gist.github.com/1519641
This code is untested so might need some work, but will point you in the right direction.
Campbell McArthur says
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;
}
}[/PHP]
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;
}[/CODE]
Here is what it looks like in action http://www.lostplanet-techbloggers.com
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!
Campbell
Bill Erickson says
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.
Campbell McArthur says
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
Cam
John Russell says
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.
Campbell McArthur says
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.
John Russell says
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)
Campbell McArthur says
@John Russel
Actually, you are correct! I removed the background-color: #292929; and it has corrected my problem!
Thank you so much John!
Cam
John Russell says
glad you got it worked out!
André says
Thank you, that saved me hours of time!
Elliot says
Just wanted to say thanks for the logged-in content solution, just what I needed.
Tom says
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.
Thanks!
Bill Erickson says
Yep, just apply a class of ‘not-logged-in’ to the menu items you only want visible to non-logged in users. Then add this to your css: https://gist.github.com/2694255
Frank Sposaro says
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.
Thanks
Bill Erickson says
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.