When the navigation menu system was released with WordPress 3.0, it was one of the factors that turned WordPress from a blogging platform into a CMS.
It meant that you could add whatever content you wanted to your site’s navigation menus, including custom links. The drag and drop interface meant that anyone could create their own custom menu without any coding skills.
But sometimes you don’t want to rely on this. If you’re developing a site for a client who’s going to be adding pages to their site but is unlikely to update the navigation menu(s) when they do so, or don’t have the skills to, then an automated navigation menu can be useful.
In this post, I’m going to show you how to create an automated navigation menu that displays all of the pages in your site, with child pages shown as second level entries in the navigation menu.
You can then add this code to your page header in your theme, or to your sidebar or footer if you want, and it will give your users links that automatically update when new content is added to your site.
What You’ll Need to Automate WordPress Navigation Menus
To follow along with this post, you’ll need:
- A development or testing installation of WordPress, with some pages and subpages added, and
- A code editor.
All of the code is on GitHub so if you get stuck, you can interrogate that to see what you should be doing.
Setting up the Code
I’m going to add this code to a plugin so that I’ve still got it if I should change my theme in future. That way, I can then code the function from my plugin into my theme to add the navigation menu or section menu in the right place. If your theme has hooks, you could use one or more of those to add your code.
If you’re working with a third party theme that doesn’t have hooks, you’ll have to add code to the theme. Don’t code this directly into the theme: instead, create a child theme and add your code to that. Just make a duplicate of the theme template file from the parent theme that you want to edit, add that to your child theme and edit it.
The first step is to create the plugin. I’m creating a folder for mine in my wp-content/plugins folder. Creating a folder means I can add more files to the plugin in future if I need to, such as a stylesheet or include files.
First you need to add the opening code to your plugin, in comments, to tell WordPress what this is:
Now activate your plugin.
Next, if you’re using a child theme, set that up. I’m using a child of the Twenty Seventeen theme – here’s my stylesheet:
Once you’ve done this, if your site doesn’t already have some pages in it, add some. They need to have a multi-level structure. Here are my dummy pages:
Now let’s start adding the code to the plugin.
Creating a Function to List All Pages Hierarchically
We’re going to use the
wp_list_pages() function to fetch all the pages and list them out with links. But first we need to define some arguments for that. Start by creating your function and including the arguments:
The arguments are very simple – there’s just one for the level of pages we want to go down to. Setting this at
2 means that top level pages and their sub pages will be displayed, but nothing lower down.
Now let’s add the
wp_list_pages() function after the arguments:
Here’s the full function:
1.6 million WordPress Superheroes read and trust our blog. Join them and get daily posts delivered to your inbox – free!
Adding the Function to the Theme
Right now, the function doesn’t show anything anywhere on my site. To change that, we need to add a copy of the header from the parent theme to the child theme and edit that.
Start by duplicating your header file into your child theme and open it. In twenty seventeen the code for the navigation menu is in template-parts/navigation/navigation-top.php which means I need to add a copy of that file in the same location in my child theme, so that it’s called correctly from the header.php file. In your theme it may be the header.php file itself that you have to copy.
Depending on your theme, the code for the menu will be different. In twenty seventeen, this is the code I need to replace:
Edit your nav menu code to add a new function, with the existing code inside an
The conditional statements are important: first it checks if the function you added to your plugin is present (i.e. if the plugin is activated) and if so, it runs the function from that. If not, it runs the nav menu as normal.
Now let’s take a look at my site:
The links are showing up but there are a couple of problems. I don’t want it to say ‘Pages’ at the top (which is the default for the
wp_list_pages() function) and I want to order the pages more effectively. You’ll see that the home page is in the middle of the list, which isn’t ideal.
Improving the Function
Let’s go back to the plugin code and tweak it to fix those problems.
Find the arguments you already defined for
And edit it:
This adds two extra arguments:
- The markup before the list, which now says ‘Menu’ instead of ‘Pages’.
- The order in which the pages are displayed.
You need to go back to the editing screens for your pages and set the page order for each of them. Give your home page a value of
0 and the other top level pages values higher than that.
Now when you view the menu it will look like this:
You can also alter the menu order of the second level pages. These will never display above top level pages so you can start at 0 or 1 for each set of sub pages. It’s a good idea not to make these numbers subsequent, so you can slot extra pages in in future if you want to.
Automating Your Navigation Menus Can Save Work and Minimise Errors
If your site is entirely page-based, then using this technique will save you adding new pages to the menu when you create them. If you’re developing a site for a client and you’re not sure they’ll have the skills or the confidence to edit the navigation menus, then it future proofs the site and minimises the risk of error. You will need to show your client how to set the menu order for new pages, but you won’t need to teach them the menus functionality.
And if you don’t want to use this in your main navigation menu, you could always use it in your footer or after your content instead. This way your site visitors have somewhere to go after they’ve finished reading each page.