Customizing Menu Arguments

The wp_nav_menu() function has a lot of optional arguments. Here’s some examples of times you might use them:

  • Limit the depth of the menu. This is useful in a site’s footer, to have just top level menu items.
  • Change to a custom walker, like one that includes menu descriptions.
  • Change the markup that wraps the menu.

But what if you’re using the built-in menus in Genesis? Genesis specifies the arguments for wp_nav_menu() in its own functions: genesis_do_nav() and genesis_do_subnav().

Some themes I’ve seen will remove the Genesis menu and completely rebuild it (copying all the code from genesis_do_nav() ) with one or two modifications to the arguments. This is wasteful, duplicating all that code. It also could lead to issues in the future if there are changes made to the genesis_do_nav() function, like when it was updated for HTML5, and your function doesn’t contain those updates.

A better option is to use the wp_nav_menu_args filter. This runs on every menu, so you’ll want to check the theme location first.

Here’s a simple example. Let’s say your design for the primary menu will break if there’s submenu items, so we want to limit it to just top level items.

<?php
/**
* Limit Primary Menu to Top Level Items
*
* @author Bill Erickson
* @link http://www.billerickson.net/customizing-menu-arguments/
*
* @param array @args
* @return array
*
*/
function be_primary_menu_args( $args ) {
if( 'primary' == $args['theme_location'] ) {
$args['depth'] = 1;
}
return $args;
}
add_filter( 'wp_nav_menu_args', 'be_primary_menu_args' );
view raw functions.php hosted with ❤ by GitHub

When you’re looking in Genesis, it’s not obvious those arguments are filterable since this is a filter in WordPress core. Hopefully in the next version of Genesis the documentation will be updated to make this a little easier to find.

Bill Erickson

Bill Erickson is the co-founder and lead developer at CultivateWP, a WordPress agency focusing on high performance sites for web publishers.

About Me
Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk

Reader Interactions

Comments are closed. Continue the conversation with me on Twitter: @billerickson

Comments

  1. Dave says

    Great point, Bill!
    I’ve noticed similar tendencies – if someone only knows Genesis and never ventures out of the hood, they are often unaware of loads of helpful WP hooks, functions, filters, and other fun.

    I wrote an article about generating a submenu using similar techniques. It’s written with Genesis in mind, but the first time I did it I was with good old TwentyTwelve, and the method could be adapted to pretty much any WP theme. I’m always happy to find alternatives to the numbing repetition of ubiquitous bloated dropdowns.

    http://davidchu.net/blog/wordpress-automatic-submenu-genesis/
    Cheers, Dave

  2. John says

    Hi Bill!

    I have been playing with wp_nav_menu based on a snippet you made about adding list items to the end, for extra links, using the difference in arguments between the same menu at different locations to keep those added links where I don’t want them.

    My client wanted left hand navigation, so I removed the default genesis_header and genesis_sidebar and added an action to put genesis_do_header -in- the genesis-sidebar. It actually works great, just as you expect, but now when I want to make the site responsive, the aside tag comes after the content (even with a sidebar-content layout, with the sidebar on the left) so when they stack vertically, my left hand nav hides underneath the content.

    Is there a way to retrieve it to have it lead the charge? If I hadn’t pulled my header movement trick, I’ve seen it done with a few lines of hooks to reorder the content. Now that I -did- move things around I’m not sure what to target.

    Your site is an inspiration, genuinely, and you seem like a good person who cares about the community. I appreciate your insight, whether or not you can or wish to help in this one specific instance.

    • Bill Erickson says

      It’s actually not the aside tag that’s causing the issue, it’s that your sidebar loads after the content area in the HTML, so when you stack the two the sidebar is at the bottom.

      Use this code to make the sidebar load above the content area. On desktop they’ll both be floating so you won’t notice a difference, but when they go full width and stack you’ll have sidebar at the top.

      Another option is to have a mobile menu that’s used on smaller screens. Either use wp_is_mobile() to only load it on mobile devices, or just hide it on desktop and use a media query to display it on mobile.

      Or you could use Javascript to dynamically move the sidebar menu above the content area on lower resolutions.

      • John says

        Ah, thank you. I didn’t even know about genesis_get_sidebar, just the ‘do’. Hopefully it makes a difference because I’ve already removed the actions for do_sidebar and do_header before attemption the action-based transplant.

        I also, remarkably, didn’t know about wp_is_mobile. I still thought we were in that age when that kind of interpretive functionality was considered flaky. Clearly I need to do this more often! It’s funny, though, because I am continually educating myself. Oh well, one more for the arsenal.

        I’ve actually tried the Javascript one. It’s sneaky but it’s consistent and I’ve never had a compatibility issue. The effect is pretty seamless as well. It seems to have no impact on SEO because it’s the same content, not duplicated, and produced after the fact (that is, after the spider will have scoured it).

        Much obliged for your time and speed.

        • Bill Erickson says

          wp_is_mobile() isn’t the best tool, but it’s okay. It’s hard to know if the “middle” devices will be seen as mobile or not (iPad, iPad mini, android tablets…).

          If you do use wp_is_mobile(), also add styles assuming it doesn’t work. So use display:none in the main styles, then display:block in a media query targeting mobile devices.

          Yeah, I like the Javascript approach and have used it before. It’s especially useful if your sidebar has nav + a bunch of other widgets. You want just the nav up there, not all those extra widgets.

          • John says

            Just as an update: I imagine this won’t come as a surprise to you, since you’re on top of both your WordPress and Genesis game for a living, but your two-line code worked.

            I’m only surprised because I thought my five lines of scooting things around would have complicated things enough for it to not know my intentions. But it was perfect. No Javascript necessary.

            I personally think Genesis and Gravity Forms are the best things to happen to WordPress since WordPress itself. Yeah, there’s some up-front work involved, but the payoff for that work in terms of power and control is -amazing-, especially given how flexible they are and how much internal logic they have in how they are to be used.

            I absolutely owe you one.

  3. Viviane says

    Hi Bill

    Thanks for that code snippet. It helped me a lot!

    Instead of “$args[‘depth’] = 1;” I used “$args[‘level’] = 2;” because I only need the second level of the menu.

    Now I have following problem: How can I display the sub navigation ONLY if the parent is active… and not always as it is now. I downloaded the pluggin “wp_nav_menu Extended!” (https://wordpress.org/plugins/wp-nav-menu-extended/). So I could use the “child_of” parameter. Maybe it helps?

    Greetings
    Viviane

  4. Fabian says

    Sorry but it doesn’t work for me – or i am too stupid inserting the code to the right position. Perhaps somebody could help me?

    I just want to show up the parent items in my menu, and not the child ones (Privatstunden, Für Unternehmen etc. til “Für Studiobetreiber”)

    Thanks a lot
    Fabian

  5. Lee King says

    Hi Bill,

    Great tutorial. I was just wondering if there was a way to do this without the flyouts and go down a third menu. So when you click on the Primary menu, the secondary menu opens, and when you click on an item from the secondary menu a third menu opens with its sub-items.

    Thanks for any help…Lee