Custom Post Types don’t highlight in menu nav

Working on a theatrical events site. The structure requires several separate events areas, each with a top page listing events in the particular area, and corresponding individual events pages underneath the listings page. Since each of the event area pages require a different treatment, I thought this was a good situation for custom post types, using both single-[event] and archive-[event] templates for each area.

I installed Custom Post Types UI to make the custom post types (including matching custom taxonomy) and Advanced Custom Fields to make meta fields. So far so good. The Archive custom post type (full listing of area events) pulls meta from the Single custom post type, and both custom post pages display correctly except for one thing: the main nav menu no longer highlights the active web page on the Archive listing. [Note: there are many posts about how to highlight submenu Single custom posts to match parent; I don’t need that, just need the current Event Area to highlight correctly in main menu nav!]

Read More

I realized I had constructed my main nav – which includes the event areas – with wp_nav_menu and register_nav_menus. So the event areas corresponding to Archive custom posts were originally constructed as Pages and the main nav was set up using WP Menu’s drag and drop capability. WordPress correctly defaults to the archive-[event] custom post template (and ignores the existing Page with same name), and the nav menu is functional in terms of links, but doesn’t highlight the Archive custom post link in the nav. Pages in the main nav work correctly.

When I check output on Event Area, there is a “current_page_parent” class attached to the Blog nav, but no “current-menu-item” elsewhere, which I guess is appropriate for custom posts. I suppose if wp_nav_menu is just for Pages, this makes sense as the top-level archive posts won’t be recognized, but I have no clue how to fix it. I’m will to try hacks, but want to avoid ID-specific ones or jQuery if possible. One thought would be to chuck the archive-[event] template, and use a regular page template for the listing while keeping the true single-[event] custom type post. Any reason faking it that way couldn’t work? Thanks for any advice, hope I’m missing obvious/easy approach.

Related posts

Leave a Reply

3 comments

  1. I have always considered this a bug, but if not, it’s pretty disconcerting. You have 2 things to fix: the first is to not highlight the “Blog” top-level item, and the second is to highlight the appropriate top-level item under which your single CPT resides.

    There might be other methods, but I’ll share my method, which unfortunately, DOES target the menu ID’s with CSS.

    To the nav container, add a conditional that identifies when the nav is being displayed on the single CPT:

    <nav class="navsf<?php if (is_singular('news')) { echo ' fixhilite'; } ?>">

    Then you’ll need to get the id’s for the “Blog” menu item and for the CPT parent Menu Item (in this example, “News”). Let’s say for “Blog” it’s the following:

    <li id="menu-item-29" ...>

    And for “News” it’s:

    <li id="menu-item-30" ...>

    In your CSS, you might target these items like so to change text or background colors to highlight/un-highlight things accordingly:

    .navsf.fixhilite li#menu-item-29

    .navsf.fixhilite li#menu-item-30

  2. your problem is probably solved already long time ago. Anyway, here is may solution:

    public static function WPFilter_UpdateNavMenuCSS($classes, $item) {
        $pages = get_posts ( array (
                                    'post_type' => 'page', 
                                    'meta_key' => '_wp_page_template', 
                                    'meta_value' => 'page-works.php' ) );
        if (is_array ( $pages ) && count ( $pages ) > 0) {
            $root_page = $pages [0];
            if (is_singular ( self::id )) {
                if (( int ) $root_page->ID == ( int ) $item->object_id) {
                    $classes [] = 'current_page_parent';
                } else {
                    $key = array_search ( 'current_page_parent', $classes );
                    if ($key) {
                        unset ( $classes [$key] );
                    }
                }
            }
        }
        return $classes;
    }
    

    Just modify this method according your needs. You have to replace page-works.php and self:id accordingly.

    For next you have to register filter to call method defined above:

    add_filter ( 'nav_menu_css_class', 'SimpleThemePostTypePortfolio::WPFilter_UpdateNavMenuCSS', 10, 2 );
    

    This solution requires that you have a custom page template to show list of your custom post type and this template is chosen for page, which you want define as parent page.

  3. I suggest to use jQuery like:

    <?php if(is_singular('your-custom-post-type')) : ?>
    
        <script>
            (function($) {
            $(document).ready(function() {   
                $('#menu-item-20').addClass('current-menu-item');
            });
            })(jQuery);
        </script>
    
    <?php endif; ?>
    

    Done.