Highlight hierarchical ancestor menu items for pages and posts (e.g. custom taxonomy and terms)

I have tested and confirmed the following works with a Nav block containing a Menu block and a standalone Menu block.

The code does two things:

  1. Makes nav/menu items highlight when they are logically hierarchical ancestors based on the URL
    e.g. https://site.com/type will be highlighted if what is being currently viewed is a page or post with the url https://site.com/type/some-page-or-post
  2. Makes nav/menu items highlight when they are hierarchically related by custom taxonomy
    e.g. when a viewing a post, the taxonomy terms related to it will be highlighted.

This may require tweaking for some custom configurations but should cover most normal hierarchical scenarios.

Firstly, you will need to add the below custom code to your site:

function string_starts_with($haystack, $needle) {
    return $haystack[0] === $needle[0] ? strncmp($haystack, $needle, strlen($needle)) === 0 : false;
}

function update_menu_item_classes( $classes, $item ) {
	global $post;
	$front_page_id = (int) get_option('page_on_front');
	$item_id = (int) $item->object_id;
	if (is_single() && ($item_id !== $front_page_id)) {
		$post_url = get_permalink($post);
		$post_type = $post->post_type;
		if ($post_type == $item->object || string_starts_with($post_url, $item->url)) {
			$classes[] = 'current-page-parent';
		} else {
			$post_taxonomies = get_object_taxonomies($post);
			if (! empty($post_taxonomies)) {
				foreach ($post_taxonomies as $matched_term_type) {
					if ($matched_term_type != $item->object) {
						continue;
					}
					
					$matched_terms = get_the_terms( $post, $matched_term_type );
					$term_slug = '';
					if( ! empty( $matched_terms ) ) {
						foreach ( $matched_terms as $term ) {
							$term_slug = $term->slug;
							break;
						}
					}

					$menu_item_term = ($matched_term_type != 'category') ? get_term($item->object_id) : get_category($item->object_id);
					if ($term_slug && $menu_item_term->slug == $term_slug) {
						$classes[] = 'current-menu-item';
						break;
					}	
				}
			}						 
		}
	}
	return $classes;  
}
 
function highlight_custom_posts_taxonomy_menu_items( $items ) {
    foreach ( $items as $key => $item ) {
		$item->classes = update_menu_item_classes($item->classes, $item);
    }

    return $items;
}

add_filter( 'wp_get_nav_menu_items', 'highlight_custom_posts_taxonomy_menu_items' );

For information on how to add custom code, please see the following tip:

Then add a global class to your Nav or Menu block (e.g. called nav).

Finally, add these relative styles to the global class as required.

For Menu:

For Nav:

You can add any styling you want to these relative styles, such as make the text bold or change the colour of the text, etc:

Note: currently this will not highlight a menu item that is a root relative custom link (e.g. “/some-folder/”) as WordPress posts have a full URL.

1 Like

Thank you StrangeTech, I really appreciate all your work! Unfortunately, I am not getting it to work.

Just for clarification - If I use the Cwicly Menu block I need to add the php code through a code snippet. Then add a class to the menu block.

From my understanding, only the first screenshot “For Menu” is relevant if using the default Cwicly Menu Block . Do I need to add the second relative style “current sub nav links” as well?

Thank you.

Hi @Alexander,

Once you have added the custom code and added global class to the Menu block that has the For Menu relative style, it should work without requiring any other changes.

If you share a link to your site, it will be easier and faster for me to help you work out what the issue is.

Here is the link to an actual CPT single page where the main menu item “Work” should be highlighted in blue: Dorfkrug Bar Grill – new.olex-design.com

Attached are two screenshots showing the relative styling panels.

Thanks again!

Hi Alexander,

Two things:

  1. Can you show how you are adding the custom code (it doesn’t seem to be applied).
  2. Please add a relative style rule for a.current-page-parent (after a comma in the current menu links relative style) - this should make your work menu item highlight straight away.

Hi StrangeTech

I have adjusted the relative styling rules (please see attachment) but it’s still not working.

This is how I have added the code snippet - Part 1

And Part 2:

OK, I don’t know why the code is not applying to your menu, but I have worked out that the relative styles are being overridden because you are setting the initial colour and hover colour using the built-in Menu styles.

Here is the solution:

For you relative styles in your navigation global class, please update them to be the following:

.cc-menu>li>a.current
.cc-menu>li>a.current-menu-item
.cc-menu>li>a.current-menu-ancestor
.cc-menu>li>a.current-page-parent

This should make everything work from the style side.

Let me know how you get on.

Just checking if this snippet is active and being applied to the frontend as it is strange that it is not working on your case.

Also, please can you show me how you have configured your menu items in Appearance > Menus.

Thank you for your patience StrangeTech.

This is the menu setup under Appearance > Menu

Maybe this setup is also relevant - the relative styling:

@Alexander Just want to make sure you saw this.

Unfortunately I can’t get this to work. I have no idea how to add to relative styles to the little dialog window.

This whole situation is driving me mad - I guess you too )

I was hoping to give you this in a quick way so you could input it in free-form, unfortunately there appears to be a bug in Cwicly that is preventing this.

I am really busy at the moment, as soon as I have a moment, I will update my version and send you a screenshot of how to do it.

1 Like

Thank you StrangeTech. I really appreciate this!