Tutorials Web Development

How to Build WordPress Navigation Using wp_nav_menu()

2.25/5 (4)

Every modern WordPress theme should include many common elements within the code. Hard-coding a manual navigation works if you've already created the content, but it is not very dynamic at all.

The best method would be creating your own WP navigation programmatically which an administrator can then tie into one of their own menus.



For this article I'd like to go over the fundamentals you should follow when creating your own navigation in a theme. Specifically going over the many custom options and how you can setup a brand new menu from scratch. You won't need to create anything for this article so think of it more like a reference guide when coding.

Basics of a Nav Menu

Back before the many advancements of WordPress 3.0 developers typically used wp_page_menu() in theme development. This will output a full list of pages along with a homepage link, and you have some parameters which are outlined in the codex. You might still use this in your sidebar or footer area if it makes sense.

But the much more popular method of navigation is through WordPress' built-in menu system. Administrators may create as many custom menus as they like, dragging & dropping links to create manual hierarchy and structure. You can directly manage links to posts, pages, categories, tags, practically anything on your site.

The first step is to write some code in your functions.php file which creates the navigation menu. This may be done with register_nav_menu() or register_nav_menus() if you have multiple items. These menus only require a single identifier called $location along with a small descriptive string.

1
register_nav_menu( 'primary', 'Primary Menu' );

$location is more like a slug ID used to identify the menu in your theme. You'll reference this defined item inside any PHP theme file you need it to appear. Also note that nav menus will auto-initialize theme support so you do not need to use add_theme_support() for menus.

 

Positions in your Theme

With your menu(s) setup in functions.php we should move on to the other theme files. Let's start in a typical location such as header.php where we can add some very basic code. This sample is copied from the wp_nav_menu() codex and includes all of the optional parameters.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$defaults = 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( $defaults );

I'm going to delve into these options more in the next section. But I'll start by glossing over the first two. Please remember that all of these are optional, because the values you see above will become your default if not overwritten. theme_location should match the location slug you chose when registering the menu. This is the only value that you should change to ensure it matches up properly.

Sometimes people confuse the menu location with menu since they are both very similar. In fact, menu should almost always be omitted which then allows the webmaster to assign their own menu to that location. This menu parameter is used to include a pre-made admin menu. It should be identical to a pre-existing menu that has already been created. But since most people will not have an existing menu(or this could change between websites) it's best practice to simply leave it out of your theme navigation.

 

Setting Parameters

The other settings are mostly for customization which is why you could ignore them. But let's tackle the rest so we have a good understanding of the possibilities. container, container_class, and container_id are beneficial when styling the menu. The outer container element wraps around the UL so it could even be an HTML5 <nav> if you like semantics.

The menu_class and menu_id get applied onto the unordered list itself. Each menu gets a class of .menu, so you might wish to change this if you're using more than one. The echo param tells this function to output the HTML menu, otherwise it will return the value back to a function or PHP variable. When wp_nav_menu() cannot run for any reason, it will automatically fallback to using wp_page_menu() as I mentioned earlier.

The next two before and after params will output any HTML just before each of the anchor links, or just after closing them. link_before and link_after will append HTML inside the anchor links, just before & after the text itself. Remember these options and be sure not to get them mixed up! When in doubt, check the codex for support.

Now if you do not want to use an unordered list you can change this inside items_wrap. It's using a sprintf() type of syntax to replace values with dynamic parameters in the same function. %1$s refers to menu_id, %2$s refers to menu_class, and %3$s is related to the list items output. Since it takes a whole lot of extra work to change the <li> elements it is usually best to just leave this one alone.

Finally the depth parameter tells the menu how deep we should go for hierarchy. If our header navigation is only a single-tier dropdown menu then we only need 1 level of depth. Or we may have a 2-tier flyout menu which could use 2 levels of depth. -1 is a special value which displays all links in the menu, but condenses them together into the same display level.

Now the $walker item is a special parameter for customizing how WordPress outputs content in a tree hierarchy. It expects a new class object which includes customized methods for item output. This is a fairly advanced topic, but you can read more about it from the Walker class reference guide.

 

Generate Menus from WP Admin

This last bit should provide administrators & webmasters a better way to understand menus. Once logged into the admin panel hover "Appearance" and then click the menus link.

select-menu-wp-admin-screenshot

From here you should rearrange links by organizing from the left accordion into the right section. You can give the menu a name which can be referenced in PHP - but notice at the top you'll see a drop-down select menu. Once you register a navigation and give it a theme location it appears in this dropdown for the administrator to select. This is how webmasters can organize their own menus without needing to code any PHP.

From the left side you can choose between pages, posts, links, categories, and tags. If you click the small tab near the top-right corner labeled "Screen Options" you can hide some of these screen choices. You'll also find advanced menu options for giving each link a target(such as target="_blank") or even unique CSS classes.

wordpress-menus-screen-options

Each category link could use a different class for unique colors when selected. By default you'll give each link some text and a brief description, which is often used only by the website administrator. Links can also have title attributes and unique XFN values.

The more you practice using this menu system the clearer it will become. As a developer who has been using WordPress for years, I find this to be very handy. Newcomers who are just learning the basics of WordPress can still pick this up quickly without much of a struggle.

 

Further Reading

 

Closing

I hope this in-depth look at the WordPress navigation system can help new developers jump right into theming. Obviously there are some other important aspects to coding a theme. But navigation is so crucial and also somewhat confusing if you've never built something like this before. Try out these sample PHP codes and see what you can make using WordPress as the core foundation.