Make menu highlights work for custom post types
I’ve written on my own blog about how WordPress’s navigation menus are great, but sometimes need some enhancement. One area they fall down in is how they work with custom post types.
Lets say you create a custom post type called ‘resources’ (I’ve done this on a couple of sites recently – see Send My Friend to School and Flesh and Blood). You are going to make use of the built in archive that gets generated at /resources, and you’re going to put this in your menu.
There are two issues in this scenario:
- A page displaying an item(s) from a post type seems to highlight any menu item linked to the blog archive page – perhaps your “Home” link, or your “Blog” link. It does this by setting the “current_page_parent” class on that menu item to highlight it. We need to prevent this happening for the post type.
- WordPress doesn’t appropriately highlight the menu item you create that links to your post type’s archive. We need to highlight this menu item if viewing post(s) from that post type. We can do this by adding a class like “current_page_parent” to that menu item at the appropriate times.
Before we get the code, we’ll need a way to specify that a certain menu item is to be used for this purpose. To do this you need to know another little trick that you may (or may not) know about.
When editing menus, you can use the “Screen Options” menu in the top right of the edit screen to show some extra fields for each menu item. Importantly here, you can turn on “CSS Classes” from the “Advanced menu properties” section of the Screen Options menu. Once this is enabled you can add a CSS class to your menu item. The code below uses the class “post-type-xxx” where xxx is your post type’s name.
So, in summary, to use the code below you’ll need to:
- Add a menu item to your menu that links to the index of your post type
- Add the “post-type-xxx” class to the menu item as described above
- Add the code below to your functions.php, or other suitable file
- Sit back and watch the magic!
Here’s the code for the filter:
/* * This filter fixes an issue where the blog page is highlighted as a menu item * for archives/singles of other post types. */ add_filter('nav_menu_css_class', 'mytheme_custom_type_nav_class', 10, 2); function mytheme_custom_type_nav_class($classes, $item) { $post_type = get_post_type(); // Remove current_page_parent from classes if the current item is the blog page // Note: The object_id property seems to be the ID of the menu item's target. if ($post_type != 'post' && $item->object_id == get_option('page_for_posts')) { $current_value = "current_page_parent"; $classes = array_filter($classes, function ($element) use ($current_value) { return ($element != $current_value); } ); } // Now look for post-type-<name> in the classes. A menu item with this class // should be given a class that will highlight it. $this_type_class = 'post-type-' . $post_type; if (in_array( $this_type_class, $classes )) { array_push($classes, 'current_page_parent'); }; return $classes; }