Custom Secondary Menu

Custom Menus are great for sitewide menus, but what if you only want to list a section’s subpages?

In the screenshot above, you’ll see the Plays dropdown lists three subpages. And on the right side, those same subpages are listed because we’re currently in the Plays section.

There’s a few popular approaches:

  • Use wp_list_pages() to dynamically list all subpages to the current section. The downside here is you can’t easily hide items from this list, and you have to keep the page order in sync with the custom menu’s page order (so they appear in the same order). You also can’t provide custom lables for menu items. In the above example, “Current Season” is really a page called “2011-2012 Season”, and they’ll have older seasons they do not want displayed in this menu.
  • Create a custom menu for each section. It’s a lot of work maintaining all these menus, and the end user can’t easily add a new section to the site since someone will need to create a menu for that section.

Assuming your main menu has all your site’s sections and their desired subpages, we can use wp_get_nav_menu_items() to pull only the relevant subpages.

chat9 Comments

  1. says

    The WordPress ‘get_xxx’ functions are so much fun to play with. It’s like a suite of DIY tools ready for you to build with.

    Great post, Bill!

  2. says

    Bill . . . In order for this query to work, do the pages need to be child pages of a Parent page in the ‘Page Attributes’ when the page is published?

    Great post. . . I always appreciate the commented documentation in the code. I find a lot of code snippets that don’t give that detail. It is very helpful and valuable to us intermediates. Helps us learn!

    • Bill Erickson says

      Yes, they need to be child pages of a parent page, and the top level in that hierarchy needs to be in the menu.

      So if you have a page structure like About > About Our Firm > John Smith
      – John Smith needs to be a child of About Our Firm
      – About Our Firm needs to be a child of About
      – The About page needs to be a top level menu item.

      So build the actual page hierarchy in the backend using page attributes, put all your top level pages as top level menu items, and then build the custom submenus however you want.

      In my screenshot, the Plays section goes about 5 levels deep. Current Season is a custom label for 2012-2013 Season, and there’s a bunch of seasons not listed in the submenu. That’s not a problem as long as the top level (Plays) is in the menu. On all pages under it, they will inherit that custom menu.

      Hope that makes sense. It’s difficult to describe, but should make sense looking at the screenshot.

  3. says

    Bill,
    Another solid article. I want to take this menu function and plug it into to two menu sections on the site. one menu would be just below the main nav on the site. And the other menu location would be just above the left sidebar.

    What would be the best way to implement that? I’m thinking I just take the code provided and modify the action hook location and the menu location to ‘secondary’ from ‘primary’. Is that right? Or is there a better way?

    • says

      Well, I did manage to get the menu setup in another area of the site. w0ot! But now it’s just a matter of optimizing the code. I’ve basically included the above code twice, modifying, of course, the functionname and the action hook areas.

      • says

        Okay, I’ve answered my own questions. I am officially stumped. I’d like to know what’s involved to make this function for children of children.

        The top Nav shows children of a top level page. Some of these children elements also have children. I’d like to show a Children of Children nav on the left. I feel like I’m describing inception. Is this method the best way, or is there another method I should look at?

          • says

            This is pretty close, Bill. Thank you! What happens now is that the children of children are pulled into the side nav menu, but the children pages are still there. If you’re on a child of a child, then only show those nav items that are 3 levels deep. I’m toying around with the snippet though. I’ll let you know if I fix it, but any tips are appreciated.

Leave a Reply

If you'd like to include code in your post, please post it to http://gist.github.com and include a link.