0

I'm building a site with a mega menu. Here's what the structure looks like:

<ul>
  <li class="active-grandparent">Grandparent
    <ul>
      <li>Parent</li>
      <li>Parent</li>
      <li>Parent</li>
      <li>Parent
        <ul>
          <li>Child</li>
          <li>Child</li>
          <li>Child</li>
          <li>Child</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>Grandparent</li>
  <li>Grandparent</li>
  <li>Grandparent</li>
</ul>

I'd like to add the class "active-grandparent" to the top level Grandparent <li> if you are on that page or a parent / child page.

WordPress gives each active <li> item a class of current-menu-item, but I need to specifically target the grandparent <li> only so I can add some styles for when it's active.

How is this achieved?

Updated As pointed out in the the comments, I could use current-menu-ancestor. However, this is only being generated on the Grandparent <li> when you're on a parent or child page.

To clarify, if you're on the top level Grandparent page (/grandparent), these are the classes which are being generated within the <li>:

.menu-item
.menu-item-type-post_type
.menu-item-object-page 
.current-menu-item 
.page_item page-item-12 
.current_page_item 
.menu-item-has-children 
.menu-item-203

If you're on a parent (/grandparent/parent) or child page (/grandparent/parent/child), these are the classes which are being generated within the Grandparent <li>:

.menu-item 
.menu-item-type-post_type 
.menu-item-object-page 
.current-page-ancestor 
.current-menu-ancestor 
.current-menu-parent 
.current-page-parent 
.current_page_parent 
.current_page_ancestor 
.menu-item-has-children 
.menu-item-203

If it helps, here are how my menus are generated within the template file:

<nav class="sidebar-navigation">
  <ul>
    <?php
      $menu = array( 'container' => false, 'menu_class' => false, 'items_wrap' => '%3$s' );
      // Left
      wp_nav_menu( array_merge(
        array( 'theme_location'  => 'left' ),
        $menu
      ) );
      // Right
      wp_nav_menu( array_merge(
        array( 'theme_location'  => 'right' ),
        $menu
      ) );
    ?>
  </ul>
</nav>
  • It should get the class current-menu-ancestor or similar already. – Jacob Peattie Aug 6 '18 at 12:43
  • current-menu-ancestor is only being generated on the Grandparent <li> when you're on a parent or child page. I've updated my question. – Sam Aug 6 '18 at 13:35
  • will you not achieve the same in this way: .active-grandparent = ul.menu-class > .current_page_item, ul.menu-class > .current-menu-ancestor ? – nmr Aug 6 '18 at 13:49
  • I need to apply specific styles to Grandparent '<li>', not the parents or children. – Sam Aug 6 '18 at 13:51
  • Yes, > char ensure that this styles will be be applied only to first .current-menu-ancestor or first .current_page_item under ul.menu-class. See here . – nmr Aug 6 '18 at 14:06
2

Styling the top-level item if it's active or a child is active is possible with pure CSS. Use the child selector, >, from the top:

.sidebar-navigation > ul > .current-menu-item,
.sidebar-navigation > ul > .current-menu-ancestor {}

If you want to add a new class, you can use the nav_menu_css_class filter. One of its parameters is $depth, which you can use to affect only top-level items. To tell if it's child is active you can just check for the existence of the current-menu-item or current-menu-ancestor classes:

function wpse_310629_nav_menu_css_class( $classes, $item, $args, $depth ) {
    if ( $depth === 0 ) {
        if ( 
            in_array( 'current-menu-item', $classes ) || 
            in_array( 'current-menu-ancestor', $classes ) 
        ) {
            $classes[] = 'active-grandparent';
        }
    }

    return $classes;
}
add_filter( 'nav_menu_css_class', 'wpse_310629_nav_menu_css_class', 10, 4 );
  • Thank you for both solutions, especially the functions alternative. – Sam Aug 6 '18 at 14:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.