A WordPress website wouldn’t be much without its menus and submenus. Customizing those menus to your liking from within WordPress is also straightforward. As such, your WordPress menu is a ‘front line’ tool to get a high search ranking and keep visitors on site.

The dedicated screens within WordPress belie how complex your menus can be. You’re also able to display menus in several locations on your site. If you have the coding skills, you can customize your WordPress menu with almost infinite possibilities.

For this post, we’re going to give you an in-depth guide to creating a WordPress menu. We’ll also show you how to take the functionality and enhance it in a few different ways.

Check Out Our Video Guide to Creating and Customizing a WordPress Menu

The Anatomy of a WordPress Menu

For the uninitiated, a WordPress menu is often a collection of links (including dropdowns). It’s a straightforward piece of functionality that is but one “vertebra” in the backbone of your website.

An example of a WordPress menu.
An example of a WordPress menu.

We’ll get into where you will see menus on a website in more detail in the next section. For now, know that they can fit anywhere you’d like to display them. You may only have a few pre-selected options (based on widget areas). In a technical sense, though, a menu can go anywhere.

Of course, a WordPress menu is paramount for navigating a website. If you have a clear and defined navigation menu, this will help users get around your site, and it’ll keep your bounce rate down.

They also serve another purpose too: your menus help with your search engine optimization (SEO). Optimizing a WordPress menu for SEO is more about what to leave out than what you put in. For starters, you can do away with elements — such as tag clouds — and keep the number of links you include low.

While Google lets you add up to 250 links on a page, keeping your “link value” high is essential. As such, cutting down the number of external links will serve you well over the long term.

The Different Types of WordPress Menu Structures

As you might already understand, depending on your application’s needs, you can opt for different WordPress menu structures.

Header menus, for example, are the most common because they deal with primary site navigation. You will often see smaller menus above the main navigation, too, as this is an excellent place for social media icons, search bars, and more.

The website of Kinsta partner SAU/CAL has a “fly-in” menu that includes navigation and social links:

A fly-in display showing two menus.
A fly-in display showing two menus.

This menu shows that there are more use cases for a WordPress menu than navigating a site. Using WordPress’ built-in functionality (more on this later), you can create a menu for almost anything you need.

Just as popular as header navigation is the footer. You’ll often use this area to repeat your primary navigation for users who scroll down. Also, it’s an excellent place to offer more context-based links for your products and services:

The Kinsta footer menu.
The Kinsta footer menu.

You’ll also see menus within a sidebar if the site uses it:

An example of sidebar navigation.
An example of sidebar navigation.

While you won’t see primary navigation here in many cases, it’s a traditional place for social links, blog post archives, and much more.

How to Create a Custom WordPress Menu (3 Methods)

Creating a WordPress menu is a no-nonsense process, regardless of your level of expertise. There are three main ways to get the job done: use WordPress’ built-in functionality; install a suitable plugin or get your hands dirty with code.

Next, we’ll show you how to create a WordPress menu using all three approaches.

1. Use WordPress’ Built-in Functionality to Create Your Menu

WordPress has built-in tools to help you create a menu. A dedicated screen within the WordPress admin will be familiar to all but the newest users.

The WordPress menu screen
The WordPress menu screen.

Of course, using the native functionality to create your WordPress menu has numerous benefits. For starters, you have complete compatibility with your site. Also, you can build your menus using a familiar interface and native tools.

To get there, head to the Appearance > Menus page within WordPress:

The WordPress Menus link.
The WordPress Menus link.

This screen divides into a few different sections. At the top, you’ll find the option to select a current menu or create a new one:

The menu selection dropdown.
The menu selection dropdown.

If you decide to build a new menu, give it a name and check out the Menu Settings section:

The Menu Settings section.
The “Menu Settings” section.

There are a lot of checkboxes here, but you’ve got two main decisions to make:

  • Add top-level pages to the menu automatically. “Top-level” here means pages you’d create within WordPress that aren’t children of other pages. For example, a blog post isn’t a top-level page because it will have a parent archive page in many cases (e.g. /blog). On the other hand, a contact page is often top-level because it won’t usually have a parent page.
  • The menu location. Each theme will have its menu locations. Unless you alter your theme’s core files, the theme developers have hard-coded these menu locations. Some themes may allow you to customize them through their settings.

Once you’re ready, click the Create Menu button. The screen will refresh and will show that you’re in your new menu. Next, take a look at the left-hand side of the screen:

The menu items accordion menu.
The menu items accordion menu.

This screen lists all the posts, pages, taxonomies, and other linkable assets on your site. You build your menu by checking boxes on the left, then clicking the Add to Menu button.

That’ll move them to the central section of the Menus screen:

Dragging and dropping items in the Menu structure section.
Dragging and dropping items in the Menu structure section.

Here, you can drag and drop menu items into place. If you click the expansion arrow next to each item, you can also set a label for your menu item or remove it:

Expanding a menu item.
Expanding a menu item.

Once you click Save Menu, you’re good to go. If you expand the Screen Options menu at the top of the screen, though, there’s more you can do with your WordPress menu:

The Screen Options panel.
The Screen Options panel.

The Screen elements group lets you show menu meta boxes in the left-hand sidebar. In contrast, the Show advanced menu properties group displays link targets, descriptions, and CSS classes for list items.

There’s one more aspect of the Menus screen worth noting. The Custom Links box lets you set a link of your choosing, rather than a predefined page on your site:

The Custom Links meta box.
The Custom Links meta box.

This option is how you can add social media links to your WordPress menu. The platform will pull the correct icon for you based on the site you select, giving you the opportunity for well-displayed logos for the sites you choose.

2. Use a Plugin to Create Your Custom WordPress Menu

The immediate solution for adding functionality to WordPress is through plugins. The previous section has covered why WordPress’ native option is almost all you need, but plugins can expand on that functionality.

There’s a question of whether you’d need a dedicated (and additional) plugin to create a WordPress menu, although there are many good reasons for doing so. For starters, you will often make a menu based on a style you can’t access under the default setup. Specific responsive designs, “mega menus,” and more are all available to you through plugins.

What’s more, you can build menus using a dedicated editor and choose from preset templates in lots of cases. Coupled with extensive customization options, you have a “no-code” solution that will provide a WordPress menu that works for your site.

For example, the Max Mega Menu plugin offers no surprises in what you can achieve:

The Max Mega Menu plugin.
The Max Mega Menu plugin.

Once it’s installed and activated, you’ll find a new Mega Menu panel within WordPress:

The Menu Locations link within WordPress.
The Menu Locations link within WordPress.

If you look at the Menu Locations screen, you’ll notice that there are more customizations available to you:

The Menu Locations screen for Max Mega Menu.
The Menu Locations screen for Max Mega Menu.

You can also apply menu themes and edit them with a similar scope to some of the best page builders on the market:

The Menu Themes screen in Max Mega Menu.
The Menu Themes screen in Max Mega Menu.

There is a lot more we could dig into here, though we’d be repeating ourselves. We encourage you to check out our previous post on WordPress menu plugins. We go into detail on how to choose the right plugin for you and how to use it.

3. Write Code to Create Your Custom WordPress Menu

Coding your own WordPress menu is a reliable way to achieve your goal for the brave (or if you’re a developer creating a new WordPress theme). Of course, you’re not going to crack open a code editor on a day-by-day basis to add a menu. For that, you’ll use the native WordPress tools (or maybe a plugin).

That said, learning how to code a WordPress menu is a vital requirement if you want to develop themes. There are four parts to success:

  • Register your menu.
  • Display the WordPress menu on the front end.
  • Show additional content within your menu or its items.
  • Define a callback.

We’ll assume that you’re handy with a code editor, you have a development environment to work in, and your skills are sharp. If you don’t yet have a theme to work with, you could use WordPress’ default options or pick one from our list of fastest WordPress themes.

When you’re ready, you’ll want to open the theme’s functions.php file. Note that this is different from the general WordPress file of the same name. Here, you need to register your menu. In other words, you have to tell WordPress what to display on the Appearance > Menus page. To do this, you use the register_nav_menus() function:

function register_my_menus() {
  register_nav_menus(
    array(
      'header' => __( 'Header Menu' ),
      'other' => __( 'Other Menu' )
     )
   );
 }
 add_action( 'init', 'register_my_menus' );

This code tells the Manage Locations tab within WordPress to display two menus: Header Menu and Other Menu:

Registering menus in WordPress.
Registering menus in WordPress.

Next, you have to display your menu using the wp_nav_menu() function. You’ll add this into the template file that corresponds with where you’d like to display the menu. In our case, we’re going with the header, so we’ll add the following code to our theme’s header.php file:

wp_nav_menu( array( 'theme_location' => 'header' ) );

It could be that this code is wrapped in an if statement, along with some of your other menus, so you’ll want to follow the conventions you find.

At this point, you could work with the menu in WordPress much like any other. Though, you may also want to consider adding additional content to your menu items. For example, you can expand the defined array to include HTML tags that will render on output:

wp_nav_menu(
  array(
    'menu' => 'primary',
    'link_before' => '',
    'link_after' => '',
  )
);

Your final task here is to define a callback. By default, WordPress displays a populated menu when the specified one isn’t found. As an alternative, WordPress will display a menu of pages when no custom menu is selected. If this isn’t your desired action, you can set a different parameter for the theme-location argument and also add in a fallback_cb argument:

wp_nav_menu(
  array(
    'menu' => 'primary',
    // do not fall back to first non-empty menu
    'theme_location' => '__no_such_location',
    // do not fall back to wp_page_menu()
    'fallback_cb' => false
  )
);

Once you understand how to create a WordPress menu, you can begin to enhance the functionality. We’ll look at this in our final section to create a custom menu meta box for WordPress.

 

How to Enhance Your WordPress Menu

Because this section is advanced, we’ll make some assumptions before we continue:

  • You know how to create a WordPress menu using PHP.
  • Your PHP skills are good enough to follow along with some advanced topics.
  • You know how to register and initialize a WordPress plugin.

It’s beyond the scope of this article, but you can use the WordPress Plugin Boilerplate Generator to create a new, standardized plugin template.

The WordPress Plugin Boilerplate Generator.
The WordPress Plugin Boilerplate Generator.

When you’re ready, create and upload your plugin to WordPress:

A fresh plugin installed within WordPress.
A new plugin installed within WordPress.

Next, navigate to the plugin’s folder and open the main file. Here, add the following code:

/**
 * Add menu meta box
 *
 * @param object $object The meta box object
 * @link https://developer.wordpress.org/reference/functions/add_meta_box/
 */
function custom_add_menu_meta_box( $object ) {
    add_meta_box( 'custom-menu-metabox', __( 'Authors' ), 'custom_menu_meta_box', 'nav-menus', 'side', 'default' );
    return $object;
}
add_filter( 'nav_menu_meta_box_object', 'custom_add_menu_meta_box', 10, 1);

The WordPress add_meta_box() function will register a meta box within the WordPress admin. There are a few arguments you’ll want to reference within the official documentation. We also use the nav_menu_meta_box_object() filter because there is no action within the nav-menus.php file to hook into. This statement determines whether the function adds a menu item’s meta box for an object type. When the filter runs, add_meta_box registers the custom meta box.

Defining a Callback Function

Next, we can define a callback function to produce the HTML content for the meta box:

/**
 * Displays a metabox for an author menu item.
 *
 * @global int|string $nav_menu_selected_id (id, name or slug) of the currently-selected menu
 */
function custom_menu_meta_box(){
    global $nav_menu_selected_id;
    $walker = new Walker_Nav_Menu_Checklist();
    ...
}

The global variable remembers the current menu ID, while $walker stores a new instance of the Walker_Nav_Menu_Checklist object. That’ll build the HTML list of menu items.

From here, we have to determine the active tab in the custom meta box. To do this, we set the value of $current_tab, working within the ellipsis set in the previous code block.

We’re using two tabs here, but you can add as many as you need:

$current_tab = 'all';
if ( isset( $_REQUEST['authorarchive-tab'] ) && 'admins' == $_REQUEST['authorarchive-tab'] ) {
    $current_tab = 'admins';
} elseif ( isset( $_REQUEST['authorarchive-tab'] ) && 'all' == $_REQUEST['authorarchive-tab'] ) {
    $current_tab = 'all';
}

The following line will get all users with write privileges and add many properties to the $authors object:

$authors = get_users( array( 'orderby' => 'nicename', 'order' => 'ASC', 'who' => 'authors' ) );
$admins = array();

/* set values to required item properties */
foreach ( $authors as &$author ) {
    $author->classes = array();
    $author->type = 'custom';
    $author->object_id = $author->nickname;
    $author->title = $author->nickname . ' - ' . implode(', ', $author->roles);
    $author->object = 'custom';
    $author->url = get_author_posts_url( $author->ID ); 
    $author->attr_title = $author->displayname;
    if( $author->has_cap( 'edit_users' ) ){
        $admins[] = $author;
    }
}
$removed_args = array( 'action', 'customlink-tab', 'edit-menu-item', 'menu-item', 'page-tab', '_wpnonce' );
?>

Here, get_users returns an array of $user objects selected by the specified parameters. The who parameter will force WordPress to query the database for users who have writing privileges.

Also, the $admins array will store an array of authors, while $removed_args will store a list of query variables to be removed.

You can now print the meta box markup. To do that, let’s build the tab labels and links.

<div id="authorarchive" class="categorydiv">
	<ul id="authorarchive-tabs" class="authorarchive-tabs add-menu-item-tabs">
		<li <?php echo ( 'all' == $current_tab ? ' class="tabs"' : '' ); ?>>
			<a class="nav-tab-link" data-type="tabs-panel-authorarchive-all" href="<?php if ( $nav_menu_selected_id ) echo esc_url( add_query_arg( 'authorarchive-tab', 'all', remove_query_arg( $removed_args ) ) ); ?>#tabs-panel-authorarchive-all">
				<?php _e( 'View All' ); ?>
			</a>
		</li>

		<li <?php echo ( 'admins' == $current_tab ? ' class="tabs"' : '' ); ?>>
			<a class="nav-tab-link" data-type="tabs-panel-authorarchive-admins" href="<?php if ( $nav_menu_selected_id ) echo esc_url( add_query_arg( 'authorarchive-tab', 'admins', remove_query_arg( $removed_args ) ) ); ?>#tabs-panel-authorarchive-admins">
				<?php _e( 'Admins' ); ?>
			</a>
		</li>
	</ul>

Remember to assign the correct class names, IDs, and data attributes to the meta box elements; otherwise, the menu won’t work as expected.

Both add_query_arg and remove_query_arg functions set tab-specific values for the authorarchive-tabs variable and remove unnecessary variables.

At this point, we have a meta box with defined tabs:

Unpopulated tabs within the Authors meta box.
Unpopulated tabs within the Authors’ meta box.

Our next step is to build the tabs’ HTML content.

Building the HTML Content for the Meta Box Tabs

You’ll want to follow the code in the previous section within the custom_menu_meta_box() function. To build the content, use the following within the <div> tag you wrote in the last section:

<div id="tabs-panel-authorarchive-all" class="tabs-panel tabs-panel-view-all <?php echo ( 'all' == $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' ); ?>">
	<ul id="authorarchive-checklist-all" class="categorychecklist form-no-clear">
	<?php
		echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $authors), 0, (object) array( 'walker' => $walker) );
	?>
	</ul>
</div>

<div id="tabs-panel-authorarchive-admins" class="tabs-panel tabs-panel-view-admins <?php echo ( 'admins' == $current_tab ? 'tabs-panel-active' : 'tabs-panel-inactive' ); ?>">
	<ul id="authorarchive-checklist-admins" class="categorychecklist form-no-clear">
	<?php
		echo walk_nav_menu_tree( array_map('wp_setup_nav_menu_item', $admins), 0, (object) array( 'walker' => $walker) );
	?>
	</ul>
</div>

In short, each tab contains a list of checkboxes. The walk_nav_menu_tree() function prints the list using three arguments: $items, $depth, and $r – all required.

The $items array stores an array of admin users. The array_map() function applies the wp_setup_nav_menu_item() function to $admins and adds menu item properties to the array elements.

The Authors meta box, populated with users.
The Author’s meta box, populated with users.

From here, we can add the finishing touches.

Adding a Submit Button

Most of the custom meta box is complete, although we still need to add a Submit button and a processing “spinner” icon.

Here’s a short piece of code that you can place straight after the previous block:

<p class="button-controls wp-clearfix">
	<span class="list-controls">
		<a href="<?php echo esc_url( add_query_arg( array( 'authorarchive-tab' => 'all', 'selectall' => 1, ), remove_query_arg( $removed_args ) )); ?>#authorarchive" class="select-all"><?php _e('Select All'); ?></a>
	</span>
	<span class="add-to-menu">
		<input type="submit"<?php wp_nav_menu_disabled_check( $nav_menu_selected_id ); ?> class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e('Add to Menu'); ?>" name="add-authorarchive-menu-item" id="submit-authorarchive" />
		<span class="spinner"></span>
	</span>
</p>

</div>
<?php
}
The finished Authors meta box within WordPress.
The finished Authors meta box within WordPress.

With this knowledge, you can add almost any functionality to your menus! Note that there’s also a public Gist of the plugin on GitHub that’s available to download for free.

Summary

A WordPress menu is a crucial aspect of your site. Because of this, the platform offers a native and powerful panel that will let you customize every menu on your site. However, it won’t provide everything you need by default.

Several screen options help you to add CSS tags and more. Also, installing a plugin will let you turn your native menus into mega menus and work with enhanced functionality to make yours more responsive (among other facets). Coding is also a possibility, and although it’s a challenging task for a novice coder, it’s something you can put together in the space of an afternoon.

Do you want to customize your WordPress menu, and if so, what approach are you going for? Share your thoughts and opinions in the comments section below!

Salman Ravoof

Salman Ravoof is a self-taught web developer, writer, creator, and a huge admirer of Free and Open Source Software (FOSS). Besides tech, he's excited by science, philosophy, photography, arts, cats, and food. Learn more about him on his website, and connect with Salman on Twitter.