Wordpress

Auto Create Navigation Tabs for New Pages

OK, I've had a number of inquiries about setting up navigation tabs to be automatically created when new pages are published (just pages, not posts). Specifically, these inquiries are about my WordPress theme, This Just In!, but this technique can be adapted to any theme to achieve the same effect.

Introduction

OK, so our problem we're trying to solve here is how to automatically create main navigation tabs when we create new pages so that we don't have to edit the code every time we want a link to a new page in our main navigation menu.

The main problem we're going to run into here is that we don't want to include every single page, otherwise, as you add pages that main navigation menu is going to grow wider than it's container, which will cause it to wrap to a new line...and that'll look terrible.To solve this problem we need to have a way to limit the number of tabs that are automatically added to our navigation menu. Now, we could just limit the number of links to the most that will fit on one line, but that isn't an ideal solution for two reasons.

First of all, the nav tabs on This Just In! stretch to accommodate the text inside them. So, a limit of 10 links may be OK for one blog if the anchor text is short, but for longer anchor text, those tabs will stretch to accommodate the anchor text within them and 10 tabs may be too much, causing the menu to wrap to a new line. Not good.

The second problem with setting a simple limit is that as we create new pages, we may want some to show up in the main nav menu, but not others. If we set a simple limit on the number of tabs in that menu, we won't have the control we may need over exactly which pages are included in the navigation menu and which are excluded.

Create a New Category?

My first thought was to create a new category to house all of our pages that we want to appear in the main nav menu and simply throw links to all those pages in that category into the main nav menu. Unfortunately, WordPress doesn't allow you to assign categories to pages, only to posts, so that idea's out the window.

Using a Page Parent?

I also considered using a page parent to act like a category. Then we could set the page parent for all the pages we want to show up in the main nav menu, and use wp_list_pages() to list all pages that are children of that parent. This may be a viable, and easy, option for some, but if you've styled child page links different from their parents you'll need to take that into account. For instance, This Just In! indents child pages under their parent page in the sidebar list of pages. That's perfect for the sidebar, but not so much for the main nav... so we'll have to go with something else.

Using Custom Fields

Luckily, WordPress does allow us to assign custom fields to any page. We'll use a custom field to mark any page that we want to appear in the main nav menu, and later add any page with that custom field to the main nav menu.

WordPress Custom Fields
The Custom Fields Area

Using a Custom Function

Once we've created our custom fields, we're going to create a function in functions.php that calls on those custom fields to determine what pages are supposed to show up in the navigation menu.

Action Steps

Creating the Custom Field

First of all, we need to locate any pages we've already created that we want to appear in the main nav menu. Edit those pages and add a new custom field...set Key to "NavMenu", and Value to "yes" (without the quotes).

Nav Menu key in WordPress custom fields
Add a NavMenu key to the custom field

Then select "Add Custom Field" button...once you've done that your Custom Fields area should look like Figure 3 here.

WordPress custom field added
You should see this after Pressing "Add Custom Field" button

Just repeat this process for any pages you want to show up in the main navigation menu.

Adding the Function Call in Place of the Current Navigation Menu

For demonstration I'll be using my This Just In! theme, but you should be able to follow along with any theme that uses a main navigation menu like This Just In!. Now you need to open up header.php in whatever you use to edit PHP files and find navigation menu code block...it looks like this in This Just In!:

1
2
3
4
5
6
7
8
<!--Main navigation menu-->
<ul>
<li><a <?php if(is_home()) echo 'class="current" '; ?>href="<?php bloginfo('url'); ?>" title="Home">Home</a></li>
<li><a <?php if(is_archive() || is_page('archives')) echo 'class="current" '; ?>href="<?php bloginfo('url'); ?>/archives/" title="Visit the archives">Archives</a></li>
<li><a <?php if(is_page('about')) echo 'class="current" '; ?>href="<?php bloginfo('url'); ?>/about/" title="About <?php bloginfo('name'); ?>">About</a></li>
<li><a href="<?php bloginfo('url'); ?>/feed/" title="RSS Feed">Feed</a></li>
<li><a href="<?php bloginfo('url'); ?>/sitemap/" title="Sitemap">Sitemap</a></li>
</ul>

Delete everything inside the <ul></ul> tags and replace it with <?php buildMenu(); ?>, so you end up with this:

1
2
3
4
<!--Main navigation menu-->
<ul>
<?php buildMenu(); ?>
</ul>

Create a Function to Build the New Navigation Menu

If you don't have a functions.php file in the root directory of your theme, create one now. Then open that file for editing and add the following function:

1
2
3
4
5
6
7
8
9
10
11
12
// Build navigation menu
function buildMenu() {
$pages = get_pages();
$key = 'NavMenu';
$pageIDs = array();
foreach($pages as $page) {
if(strtolower(get_post_meta($page->ID, $key, true)) == 'yes')
$pageIDs[] = $page->ID;
}
$pageIDList = implode(',', $pageIDs);
wp_list_pages('include=' . $pageIDList . '&title_li=');
}

Be sure your functions.php file has opening and closing tags. If you're using the latest version of This Just In!, you should already have a functions.php file in your theme directory with something already in it. Just add the buildMenu() function above what's already in the file so you end up with this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Build navigation menu
function buildMenu() {
$pages = get_pages();
$key = 'NavMenu';
$pageIDs = array();
foreach($pages as $page) {
if(strtolower(get_post_meta($page->ID, $key, true)) == 'yes')
$pageIDs[] = $page->ID;
}
$pageIDList = implode(',', $pageIDs);
wp_list_pages('include=' . $pageIDList . '&title_li=');
}
 
if(function_exists('register_sidebar'))
register_sidebar(array (
'before_widget' => '
    <li>',
'after_widget' => '</li>
',
'before_title' => '<span class="sidetitle">',
'after_title' => '</span>',
));
?>

Highlighting the "Current" Page

In This Just In!, the current page's navigation menu item is highlighted with a white background and dark text. Since we've removed our original code, which handled that for us, we'll need to create a new style in our style.css in order to replace that feature.

In the above code, we used a built-in WordPress function called wp_list_pages() to display a list of pages that were marked with our custom "NavMenu" field. One nice feature about that function is that it returns those pages as list items (<li></li>) with the current_page_item class applied if that page is currently being viewed. So, all we need to do is add something like the following to styles.css:

1
2
3
4
#nav_menu li.current_page_item a {
background: #FFF;
color: #333;
}

That first #nav_menu part may not be necessary if you're using a theme other than This Just In!.

And that's it, you've successfully set up your blog to create your navigation menu links for you. Now all you need to do is when writing a new page that you want to be included in the menu, be sure to add the custom field to that page as we covered earlier.

If you'd like to understand the code in this tutorial a little better, read on for an explanation.

Code Explanation

Ok, let's take another look at our code:

1
2
3
4
5
6
7
8
9
10
11
12
// Build navigation menu
function buildMenu() {
$pages = get_pages();
$key = 'NavMenu';
$pageIDs = array();
foreach($pages as $page) {
if(strtolower(get_post_meta($page->ID, $key, true)) == 'yes')
$pageIDs[] = $page->ID;
}
$pageIDList = implode(',', $pageIDs);
wp_list_pages('include=' . $pageIDList . '&title_li=');
}

Now let's break it down line by line

1
2
// Build navigation menu
function buildMenu() {

Comment followed by function declaration.

1
$pages = get_pages();

get_pages() is a built-in WordPress function, that returns an array of objects for all of our blog's pages.

1
$key = 'NavMenu';

Here we set the $key variable to "NavMenu" for use in the get_post_meta function below.

1
$pageIDs = array();

Next we initialize the $pageIDs array, which will hold the page IDs for the pages that have our custom field attached.

1
foreach($pages as $page) {

Simple for-each loop.

1
2
if(strtolower(get_post_meta($page->ID, $key, true)) == 'yes')
$pageIDs[] = $page->ID;

The first line uses the get_post_meta() built-in WordPress function. This function takes as parameters 1) a page ID, and 2) a custom field Key, which in our case is "NavMenu". The third parameter is true to tell the function to return a string of the first occurrence instead of an array of all occurrences of Key. Then we stick that function inside an if-statement to determine if a custom field we're looking for exists, and we check to see that the custom field contains the value 'yes'. strtolower() simply converts the string to lowercase just in case you enter something other than all lower case when setting the custom field for the page.

If that custom field exists, the second line adds the page ID to our $pageIDs array.

Then the foreach loop continues on to the next page.

1
$pageIDList = implode(',', $pageIDs);

This takes our $pageIDs array with all the page ID numbers of the pages marked with our custom field and strings them all together separated by commas using PHP's implode() function.. This is so they're in a format like 2,5,7,10,32 for the following line of code…

1
wp_list_pages('include=' . $pageIDList . '&title_li=');

wp_list_pages() is another built-in WordPress function, which, in this case, takes as parameters 1) a comma-separated list of page ID numbers, which we set up in the last step and 2) &title_li=, which tells WordPress not to return a title for the list of pages. The first parameter is a comma-separated list of page ID numbers that we set up in the previous step.

Conclusion

Now that wasn't too tough was it? Now you know how to set up WordPress to automatically create a navigation menu from pages tagged with a specific custom field. We've also lightly touched on creating a new function and using the built-in WordPress functions, get_pages(), get_post_meta(), and wp_list_pages(), as well as the php implode() function.

John Crenshaw
John Crenshaw
President
UFO company founder. 15+ years experience in performance marketing.
Never miss an update
Get more training, case studies and ideas delivered directly to your inbox.
* We never share your personal info.
View our Privacy Policy.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Let’s make something great together
Let’s talk.

Get in touch and we’ll setup a quick call to discuss your needs, what we do, and figure out if we’re a good fit.

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.