When it comes to building WordPress themes, the wp_nav_menu function is a beautiful thing. As the name implies, this function is what enables the drag-and-drop menu building interface.

Before a menu is built, if ever, the wp_nav_menu function will fallback to the wp_page_menu. For theme users, this will help visualize where their custom-built menu will eventually go, providing a probably-useful list of pages for everyone else in the meantime.

When adding menu locations with wp_nav_menu, you also have the option of using another fallback function, or displaying no fallback at all, forcing users to build a menu before anything is displayed.

Most of the time, you’ll probably want to stick with the default fallback of wp_list_pages. Here are a few use cases where you might not:

  • No fallback at all: a social links menu, which is guaranteed to be useless until the theme user fills out their social profile links
  • A category list fallback: for a non-primary menu, located directly above your latest blog posts

An example of a category list fallback can be seen in the Rovigo theme, which displays a menu between the blog heading and the latest blog posts.

Rovigo’s category list menu, highlighted in red.

In this tutorial, we’ll be focusing on the second use case: a category list fallback. If you’re familiar with WordPress theming already, you might think you can just plug in wp_list_categories as your fallback and call it a day, but it’s not quite that simple.

What happens when we use wp_list_categories as our wp_nav_menu fallback

Here’s what the Rovigo theme would look like if we used a plain wp_list_categories function as the fallback instead, using this code:

wp_nav_menu( array(
	'container' => false,
	'theme_location' => 'menu-2',
	'menu_id' => 'blog-menu',
	'fallback_cb' => 'wp_list_categories',
	'depth' => 1,
) );

This odd-looking output is derived from the default options of the wp_list_categories function, which includes a title (this is why “Categories” is displayed at the top) and markup that starts with a list item (when it should be wrapped in an unordered list).

If we were calling wp_list_categories on its own, we could override the default title_li value to correct this.

wp_list_categories( 'title_li='' );

But when used as a fallback in wp_nav_menu, we don’t have that option…directly.

Solution: Make a brand new function

While we could copy and paste the core wp_list_categories function, minus the few things we don’t like, that would be a huge violation of the DRY principle, and wholly unnecessary.

Instead, we could do something like this to leverage the existing wp_list_categories function:

function rovigo_wp_list_categories() {
	$args = array(
		'echo'             => 0,
		'title_li'         => '',
		'show_option_none' => '',
	);

	// Markup should match up when wp_nav_menu is in use too
	$output = '<ul id="blog-menu" class="menu">' . wp_list_categories( $args ) . '</ul>';

	echo $output;
}

Since wp_list_categories echos by default, we want to make sure we turn that off before storing it in $output. Overriding the show_option_none argument ensures the “No Categories” text does not display if there are no categories, which would look ugly and be pointless.

And that’s about it. This same concept can be used with other “list and dropdown functions” like wp_get_archives and wp_list_authors.

With Rovigo, wp_list_categories was a natural choice for a menu directly above the latest blog post. In your case, it’s a judgement call ultimately up to you.

Previous Article
Preventing unwanted theme updates from WordPress.org
Next Article
Preventing output of empty entry footer markup