How to Create WordPress Nav Menus: An Introduction

Navigation menus are one of the most obvious features that go into making a site. If you’re building or revising a WordPress theme, you’ll almost certainly have one or more areas where you’ll want users to be able to easily make menus. Fortunately, they’ve thought of that.

The process to create WordPress nav menus and menu areas actually has quite a lot in common with the sidebars we recently discussed. Both are common use cases that WordPress has standardized, and you’ll also notice a lot of similarities between the two APIs. If you’ve never used either, though, have no fear: we’ll cover everything you need to know.

Registering Menus: In the Theme Or In a Plugin?

One thing to stay vigilant about in WordPress site development is coupling. For the unfamiliar, in software terminology “coupling” is when two different systems rely on each other; the term is most likely to come up when things are too tightly coupled. A bit like an unhealthily co-dependent relationship, in bad tight-coupling multiple systems rely on each other too much and thus get in each others way.

themecreepDoing things like registering shortcodes, post types, and doing other intricate work in a theme is an example of unnecessary and mostly destructive coupling between the theme — which is mostly meant as your WordPress site’s display layer — and the rest of the stuff that powers your WordPress site. It’s been a while since we’ve mentioned it, by my pair of articles on “theme creep” — the problem and solutions — are a reasonable touchstone on the topic.

It’s pretty clear that most menus truly do belong in your theme.

Now that we’re properly scared of theme creep, should we banish everyone who wants to create WordPress nav menus out to a plugin? I’d argue no. With the concerns above noted, it’s still pretty clear that both widget areas and menus truly do belong in your theme. One could argue that users might want or need to have their menus persist across theme choices — but I think that’s a pretty uncommon case. Most menus need to fit well into an area allotted them by a theme.

Understanding Menus and Menu Areas

In WordPress, user-created menus are conceptually separate from the menu areas where they are displayed.

In WordPress, user-created menus are conceptually separate from the menu areas where they are displayed. In other words:

  • Developers create menu areas, which are the places in the theme where nav menus will show up.
  • Users create actual nav menus, which will appear in those menu areas.

WordPress does a rather poor job making this distinction. For example, register_nav_menu() is actually the function you use to register a menu area. (It certainly doesn’t create an actual nav menu—that’s up to the user in the admin interface.) This can get quite confusing, so keep the distinction clear and don’t let WordPress throw you for a (ahem) loop.

At first, menus and menu areas sounds a lot like the relationship between widgets and widget areas. It is similar, but with one difference: menus and menu areas are completely divorced from one another. Every widget is part of a widget area; but you could have a hundred nav menus, none of which show up in any menu area at all.

A Single Menu

You don’t have to worry about the “menu area vs. menu” distinction with a single menu and a single menu area. If a user creates a single menu, and your theme has a simple call to the function that displays menu areas, wp_nav_menu()—without any arguments—then the menu will show up where the function was called, as you’d likely expect. Just put the function call in the right place in header.php or footer.php or wherever, and you’ll get 80% of the functionality your user is likely to expect.

Multiple Menus

However! If the user has built more than one menu, or you want users to be able to display different menus in different places, or to be able to easily control what appears where, then a single call to wp_nav_menu() won’t cut it. And that’s why we have the WordPress menu area creation system—which closely resembles the process of making widget areas.

How to Tell WordPress to Make Your Menu Area Available

wordpress-manage-menu-locationsAs we said, the way in which you make a menu area — an area that users can assign specific menus to — in WordPress has a lot in common with how you make a widget area. As with widget areas, you’ll need to do essentially two things:

  1. Tell WordPress about your menu area (in functions.php)
  2. Tell WordPress how you want to display your menu area (in the relevant theme file)

So first things first: telling WordPress about your menu area. And thankfully, it’s as simple as a single command, register_nav_menu. The call has two arguments, the “slug” or nickname you want to use for your menu area location, and the name for it that you want to appear in the admin area of the site. For example:

add_action( 'after_setup_theme', 'shout_register_my_menu' );
function shout_register_my_menu() {
  register_nav_menu( 'primary', 'Primary Navigation' );

You’ll notice that, as is common in WordPress, we wrapped the call to the function in another function: we want to tell WordPress that we want a navigation menu at a specific time — after_setup_theme — and we’re calling our function with the actual call to register the menu after that. If that’s all a little confusing to you, I’d recommend you check in on our article about action and filter hooks in WordPress for a more thorough explanation of the concept.

Two Ways to Display Created Menus: By Location, or By Specific Menu ID

As we mentioned before, you can display a menu with a simple call to wp_nav_menu() without any arguments. In this section, though, we’re assuming that you want multiple nav menus in multiple places, in which case you’ll need to provide some information to the function. Below are all the arguments that wp_nav_menu() accepts, as well as their default values.

$args = array(
    'theme_location'  => '',
    'menu'            => '',
    'container'       => 'div',
    'container_class' => '',
    'container_id'    => '',
    'menu_class'      => 'menu',
    'menu_id'         => '',
    'echo'            => true,
    'fallback_cb'     => 'wp_page_menu',
    'before'          => '',
    'after'           => '',
    'link_before'     => '',
    'link_after'      => '',
    'items_wrap'      => '<ul id="%1$s" class="%2$s">%3$s</ul>', 
    'depth' => 0, 
    'walker' => '' ); 
wp_nav_menu( $args );

Practically speaking, you’ll rarely, if ever, need to specify all of these (and even understanding all of them is beyond our scope here), but I couldn’t bring myself to omit any of them. The most important piece is the first two arguments, which give you two ways to control which menus display where:

  1. theme_location — This is the “slug” we mentioned above for your menu area. You’re telling WordPress, “Find me the menu area with this slug, and then display whichever menu is currently assigned to that menu area.” You’ll probably want to use this method to display your nav menus this way most of the time, for coherence of user expectations.
  2. menu — Allows you to specify the targeted menu itself — by id, or its actual slug or name. I’ve rarely used this method, because going through the proxy of locations is helpful and allows the site admin more freedom. But you can get and display a menu this way.

And since we’re completists, here’s a summary of the other interesting arguments:

  • The various CSS and HTML control attributes — we’ll not explain them all separately, but as you likely guess, everything from the somewhat obscure before and after to the much clearer container_class are there to allow easier styling and markup compatibility.Imperial walkers on the north ridge
  • walker — This is more of an advanced usage — I’ve never had an excuse to play with it myself — but you can control the markup and dynamics of your menu in much more detail with a “Walker”. Here’s a pretty solid tutorial on it. (Alternatively, a more simplistic loop with wp_get_nav_items can do the job, as the Example in the Codex for that function shows clearly.)

That’s basically 90% of you need to know. By default, WordPress menus already contain a wealth of styling-freindly markup, so you’re pretty likely to be good with specifying either of the first two bullets to just get the menu you want an let WordPress handle the rest. And when you need to do something more complex, it’s good to know it’s all there for you.

What We’ve Learned About WordPress Navigation Menus

Hopefully, at a minimum, you now have some sense how you can create WordPress nav menus in your theme. As we said, if you only want to do the bare minimum, a call to wp_nav_menu will spit the first menu WordPress knows of out on the page right where you want it.

If you’re looking for a bit more power and control, you hopefully remember that you can use register_nav_menu, plus a more detailed use of the wp_nav_menu function, to make a WordPress menus just like the pros do. It’s not super complicated, but you master those simple elements and you’re pretty much set. Happy hacking!

Image credit: halfrain, adactio

1 Response