Category Archives: Functions

Swap menus in WordPress without a plugin

How to display a different menu in the same location as your primary menu based on page, post, template, category, or your site’s forum.

WordPress menus by design allow a unique menu to inhabit a particular location on your site. For example, the primary navigation menu is uniform across all pages with other menus possibly existing in other locations like the very top of your site, in a sidebar as a widget, or within the site’s footer as a widget. Out of the box however, WordPress does not allow selection of a different menu in the same location depending on the page you are on.

There are good reasons to show a different menu. Your site may have a members area that gives access to private areas of your site, and so you may want to have a different menu. You might want a different menu if you are a commercial client as opposed to an individual client. Or perhaps you want the public facing part of your site to have a different menu to what people in your organisation see. Whatever your reasons, read on to learn to accomplish this easy task. You do not even need to be a programmer as we will provide a good sample code for you.

Step 1 – Create the menus

Create all menus. You do this by going to Appearance > Menus. Click ‘Create Menu’ and select the pages, posts, categories, custom links, etc and then click ‘Add to Menu’. You can then add further links and you can drag and drop these links in the order you desire and also place links underneath others to that they will appear in a sub-menu. Your default menu should also be set in the ‘Primary Menu’ location. The menu or menus you wish to swap do not need to be assigned a location. In fact you cannot assign two menus to the same location using WordPress anyway.

Step 2 – Find out the ID of your alternate menu

Setup your alternative menu and find out what the ID of that menu is. You can do this by choosing a menu next to the ‘ Select a menu to edit:’ heading. Now take a look at the URL, you will see something like:
“https://wordpresssite.com/wp-admin/nav-menus.php?action=edit&menu=50 “. See the ’50’ at the end of the URL, that is the ID for the menu. Of course your menu will likely have a different ID.

Step 3 – Implement code in your theme’s function file

First you need to understand the condition you want to load your new menu. Do you want it to load based on a template, a page or pages, a category, or perhaps in your BBPress forum? Below is a sample code that loads a different menu based on a template. So all pages that use this template will load the alternate menu. Feel free to copy and paste this into your theme’s function file perhaps at the bottom of the file and then edit.

add_filter( 'wp_nav_menu_args', 'bb_wp_nav_menu_args' );
function bb_wp_nav_menu_args( $args ) {
// change the menu in the Header menu position
if( $args['theme_location'] == 'primary' && is_page_template('members.php') ) {
$args['menu'] = '20'; // 20 is the ID of the menu we want to use here
}
return $args;
}

Obviously your menu ID will probably be different and the condition as to why you want the menu to show will likely be different too. If you are happy to show a different menu based on a template you can reference an already existing template in your theme or create a new one by copying the site’s main template or other template and add it inside your child theme, Rename it to whatever makes sense to you. The below conditional references a template called ‘members.php’. You might want to call your template ‘english.php’ or ‘spanish.php’ if you wanted to display a different menu based on language, so you would swap out the reference to members.php to say spanish.php. So every page written in Spanish would then use the spanish.php template and the main menu would be in Spanish. Whatever your reason, just use a good naming scheme so it is easy for you to follow.

So, using the code above, you would change the below snippet from

if( $args['theme_location'] == 'primary' && is_page_template('members.php') ) {

to

if( $args['theme_location'] == 'primary' && is_page_template('spanish.php') ) {

That’s it.

Step 4 – Changing the function

This step is only relevant if you wish to swap the menu based on another factor like only certain pages, posts, categories, or on a unique templates like BBPress forum templates. Here is a list of functions that you can swap from the code.

Page

if( $args['theme_location'] == 'header' && is_page('1159') ) {

To find the unique ID (number) for your page, edit the page and find the number in the URL. It will look something like this: post=1159.

BBPress

if( $args['theme_location'] == 'primary' && is_bbpress('') ) {

Multiple Functions

Here is an example for using the menu based on a template and also BBPress which may use a different template. This is the whole code snippet:

add_filter( 'wp_nav_menu_args', 'bb_wp_nav_menu_args' );
function bb_wp_nav_menu_args( $args ) {
// change the menu in the Header menu position
if( $args['theme_location'] == 'primary' && is_page_template('members.php') ) {
$args['menu'] = '20'; // 20 is the ID of the menu we want to use here
}
if( $args['theme_location'] == 'primary' && is_bbpress('') ) {
$args['menu'] = '20'; // 20 is the ID of the menu we want to use here
}
return $args;
}

With the samples I have provided, you should be able to edit your code now for multiple pages, templates, and / or BBPress. Here is a list of other functions that are built into WordPress that you can use to launch your alternate menu from.

Step 5 – Styling the new menu

You can change the colour and style of your menu. By default both your main menu and alternate menu will have the same styling. Here is one way to change this.

 

  1. Install a plugin that applies unique classes to your body tag like this plugin – Ambrosite Body Class Enhanced
    https://wordpress.org/plugins/ambrosite-body-class-enhanced/
  2. Read about this plugin and how it works. In short you are able to target classes based on page, page template, and other useful variables. So in your custom style sheet you can for example target all pages using a particular template and write css to target the menu that use that template. Your CSS could look something like the following. Notice how the members template and BBPress is mentioned.

body.page-template-members .current-menu-item, body.page-template-members .current-menu-parent, body.page-template-members .current-menu-ancestor, body.bbpress .current-menu-item, {
color:#822433 !important;
}