The menu builder in WordPress is great, however quite often I find myself needing to create a secondary menu on pages, containing just a subset of the menu. In my case the rules are simple: when viewing a top level page we want to list all child pages nested beneath it. When viewing a second level page, we want to list all sibling pages nested under the same parent. We could just use wp_list_pages and filter by a parent, but it won’t match the structure designed in the menu builder.

Surprisingly there’s little information or working solutions to this problem, so I’ve put together the following code which does exactly what we want.

To give you an idea of how it works with the default options, imagine you have a menu like this:

– A
– – B
– – C
– D

If you’re on page A, you’ll see B and C in the menu (A is a top level page, so it shows children). If you’re on B or C, again, you’ll see B and C (B and C are second level pages, so it shows siblings).

A big thanks goes out to Thomas Dexter who kindly pointed out a way to use wp_nav_menu, which adds the correct wp classes and allows us to use custom walkers and the like. Using his code and the hook provided by mac joost on Stack Overflow, I created a filter that works based purely on the menu structure (irrelevant of page structure). So all you need to do is drop this in your functions.php file (remember to remove the opening <?php tag first).

Then you can display it in your theme using wp_nav_menu (just like you normally would), by passing in a sub_menu parameter to activate the custom sub_menu hook:

If you’ve copied and pasted the above code, don’t forget to change Menu Name to the slug or name of your menu.

By default, if you have many nested levels, this code will filter the menu by the absolute top level parent. If you want the menu to drill down dynamically by filtering the menu based on the direct parent, pass a “direct_parent” => true parameter to the wp_nav_menu call.

If you want to include the parent/root element in the menu, you can pass in a “show_parent” => true parameter to display the root level item.

Of course, you can continue to use the standard wp_nav_menu parameters as well. For example, if you want to limit the number of nested children being displayed, you can use the depth parameter. Or of you don’t want the menu to be displayed, you can use the echo parameter.

I hope you’ve found this post useful. If so, enjoy!