7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
  1. Code
  2. Theme Development

WordPress Theme Development Training Wheels: Day Three

Scroll to top
Read Time: 15 mins

After having dealt with manually coding various types of menus, we'll wrap up menus in this lesson covering the Custom Menus functionality introduced in Version 3.0. Custom menus allow us to freely build menus from within the WordPress admin dashboard, by adding any combination of pages, category links and other custom links, whether they be internal site links or links to any other location on the web.

Step 1: Create a Functions File

In order to make use of the custom menu feature, we need to register a special PHP function, which enables the menus feature on the theme via the register_nav_menu function. The capability to insert custom menus does not exist as a default within the theme. We need to enable this functionality specifically, and create certain menu areas or "locations" via code where our custom menus will appear.

As we'll see later, registering special functions will become quite important during more advanced theme development. In order to register functions in WordPress, we need to add a functions.php file to our theme's files.

Create a Functions File

Create a blank file named functions.php in your theme's root folder

Before we actually do anything to the functions file we can see that the Appearance > Menus in the Dashboard is pretty standard. No Menu Link to be seen.

Step 2: Register the Menu Function

Now we'll register a custom menu using the following basic form of the register_nav_menu function.

The location will be the menu's identification name for use within the code, and the description will be a nice name used to display the menu's description in the Dashboard. This would look something like the following.

"primary" would be used within the code which places the menu in the specific area of the template (location), and "Primary Menu" will be used to choose the menu location within the Appearance > Menus editing UI.

Once we've registered our menu, we can proceed to the Dashboard to create the menu via the menu editor.

The register_nav_menu function is placed within the functions.php file.

Take special care not to leave unnecessary whitespace after the functions code, as this can cause theme breakages.

Once this code is placed into your functions.php file, visit your dashboard again and refresh to see the new menu item under Appearance.

We can neaten up the registration code as we did with wp_list_pages and put the parameters into an array

Using arrays will be helpful when deciding to register more than one Custom Menu with additional parameters (coming up in a bit).

Step 3: Create a Menu via Dashboard

Now that we've registered a custom menu, we can go to Appearance > Menus to create our first Menu.

For a detailed guide on creating menus using the Menu Interface watching the following Video - WP 101 Video Training - Custom Menus

The Menu Creator interface has the following components:

  • Create new menus panel top right, which allows for creation of many different named menus
  • Custom links creator panel to add links to any URL into the menu
  • Pages panel to select existing pages from your site to the menu
  • Categories panel to add links to existing post categories to the menu

Should your site have any additional content types, for example custom post types, these will also have a panel to add to the menu.

Step 4: Placing the menu into the Theme

Placing custom menus into your theme templates requires using the wp_nav_menu() function. This function provides a location where menus built inside the dashboard can then be placed by default.

Below is the most basic form of the code needed for inserting a single menu from the menus which have been created.

Default usage:

Which results in the following HTML

What's the Result?

Firstly we notice that our original div & ul which wrapped the wp_nav_menu function are not entirely necessary as the function generates its own div and ul wrappers. What we do need to do is to specify the class and / or IDs which these will have. We will do this in a bit with some additional parameters.

The wp_nav_menu function we used does the following:

  • fetches the first menu created in the menu editor
  • adds a wrapper div, with custom class name based on the menu's name we created, with -container appended
  • adds a ul container inside of the container which has a menu class by default and custom ID based on menu name
  • creates a list of menu items with custom menu-item classes instead of page-item class

The visual result below is due to the additional wrappers which conflict with some of the CSS we have in the theme, so we'll need to edit the markup a bit and modify the placement function.

Broken CSSBroken CSSBroken CSS

Firstly we add a 'container' parameter to the placement code to tell it to generate an outer div container. The container can also be configured to generate an HTML5 'nav' tag, or with the value 'false' can be told not to generate any containing element. These parameters effectively make the markup in our theme which currently wraps the menu placement code redundant, so we can now remove them. Here's the code.

The next parameter ('container_id'), is for specifying the ID attribute of the container div, so it conforms to our CSS we've already placed into the theme.

With the third parameter ('menu_class'), we'll change the default class on the ul wrapper from 'menu' to 'bottom-menu-list' as the .menu selector has already been used in our CSS for the fallback menu styles which we'll discuss a bit later on in the lesson.

We can now place this code into the theme without the containing div and ul tags and the generated HTML should look exactly like the previous wp_list_pages and wp_page_menu functions in our previous lesson.

Better Menu MarkupBetter Menu MarkupBetter Menu Markup

The difference here of course is that we can go in at any time and add, remove or modify any of the menu items on the fly without changing any code. And here's our result.

So Now that we've got the basics covered lets put this baby through its paces a bit.

Picking up the Pace!

What we want to do as an exercise is create two Custom Menus which we will place into different locations. One in the standard position, below the header, and another in the top right side of the header.

Step 5: Registering two New Custom Menus

Using the method we've just gone through, I'm going to register two menu locations. Arrays are your friends.

It's the same as using the following two lines of code:

Just much neater and without repeating the register_nav_menu function, instead we use register_nav_menus.

Notice the "s" at the end of our function used to register more than one menu

I've registered two menus, 'top_header_menu' and 'bottom_header_menu'. We'll focus on just one of them for now, 'bottom_header_menu', which we'll be putting in place of our existing wp_page_menu code.

The code to register these menus contains:

  • the name of the menu location as we will refer to it in code when calling it for placement in the theme
  • the description of the menu which we will see reflected in the dashboard admin area where we assign menus we build to locations.

This will help us know where we're placing each menu. Now as we did earlier with our initial single primary menu which we created as a test, let's create, Header Bottom and Header Top via Appearance > Menus and add some pages, preferably different pages to each one. I've got some default ones from my demo content generator.

We've registered them, built them and added them to locations so now we can place them into our theme.

Step 6: Extending the Placement Code

Because we've created two custom menus, we're gonna need a little more than the default placement code to put into our theme so we can associate each location in the theme with a location registered via the menu registration function. We will need to add an additional parameter to the wp_nav_menu() function.

The Theme Location Parameter.

The parameter 'theme_location', which should have a value of the name of the theme location we want to connect this area of our theme with. The theme's location name should not have spaces in it, as it will be used within the functions codes which require no spaces. The name should be exactly the same as the name specified when registering the menu location.

Alternatively we could use the 'menu' parameter which explicitly fetches an already built menu from the menu builder.
The value for this parameter should be either the built menu's Name, Slug or ID. Example below.

These two options should not be used together as they will inevitably cancel each other out at some point considering the one pulls a menu based on it being assigned to a location, and the other pulls a menu based on the menu's name. Some thought needs to go into choosing one or the other.

With 'theme_location' parameter, it would be possible to reassign menus to different locations, whereas with the 'menu' parameter we are restricted to only that specific menu being pulled into the coded area in the theme.

Let's use the 'theme_location' parameter for now, seeing we will be registering two menus, which we might want to switch between the two locations. I'll add in the three parameters we dealt with earlier as well to keep it all consistent and ready to display correctly.

Which then takes the following menu we've built

Which results in the following which looks identical to what our initial code generated.

Menu One PLacedMenu One PLacedMenu One PLaced

Step 7: Placing the Second Menu

Now for that second menu which we registered and named 'top_header_menu'.

We're going to place a menu inside our header area, floating to the top right. We'll use the same type of code for placing the first menu but changing the theme location. This will facilitate us to manage two separate lists of links. For example the top header menu could contain some generic links like contact, site map and the like.

We'll use almost exactly the same code as we did with the first menu, changing the location name to reflect the name we used in registering the top menu. We'll also give it unique container ID and menu ul class. You'll notice an additional parameter at the end of this list. It's the parameter to configure what type of fallback menu we'd like to use.

A fallback menu is one which appears when no menu has been assigned to the location yet. The default fallback method is wp_list_pages(), which will create a menu from all of the pages which exist in the site currently. This is not always ideal, though it may help in cases where layout or styling depend on a menu being present in certain themes. In the case of our Top Right menu, we don't want anything to appear when no menu has been assigned, so that adding this menu is only optional, but not having it won't cause breakages. To do this we specify the value to be false.

This code will be placed within the Header div, below the site name and description.

CSS already exists in the theme to position it top right in the header. I've included the CSS for the menus at the end of this Lesson.

Final 2 MenusFinal 2 MenusFinal 2 Menus

That's the final result

Step 8: Fixing the Code for older WP

What we've done so far with the code for registering the menu functionality is very basic and on its own could be problematic. In some cases where your theme might be used on older versions of WordPress which do not support custom menus, you'd end up with errors. We need to add a layer to make the registration code backward compatible in the event that our theme is installed on older versions of WordPress.

Starting with the menu registration code we used for the two menus

We'll wrap this with a conditional argument, which will first check if the current version of WordPress supports registration of menus. It's checking if a function called register_nav_menus exists. If it does, the register_nav_menus function will be executed, if not the conditional argument will end with an endif. We'll be going through conditional arguments in much more detail a little later in on in this series.

Take care to use a colon at the end of the first part of the if function, and a semi colon after the endif.

For more detail on conditional or if statements in the mean time, view this tutorial - PHP for WordPress - Mastering Conditional Statements & Tags or the following page on the WordPress codex - codex.wordpress.org/Conditional_Tags

Much more solutions exist for Custom Menu registration, but this snippet will cover you in the vast majority of cases without turning your brain into mush. I hope.

Making Sure the Placement Code Degrades as well

We need to make sure that we still have a functional theme in cases where the custom menu functionality does not exist. We need to add an additional conditional statement to our placement code (wp_nav_menu). There are a few levels to this so pay close attention. If we don't add this extra level we'll end up with users of Pre 3.0 versions of WordPress getting nasty errors when loading this theme. You'll end up with users on old WordPress threatening to tar and feather you in the street, so best you get this part right.

1. Our placement code as it was previously

To which we will add a similar conditional argument

On its own this would mean that a site running older versions of WordPress would just display nothing. We therefore have to add an extra argument to this conditional statement so that when the answer to the if(function_exists('wp_nav_menu') comes back with a NO (meaning no the function does not exist), we can add in a fallback menu which works in WordPress pre 3.0. Here's an outline.

FYI, Text which follows // withiin PHP code will not get executed or echoed and acts like comments within the code!

And with all the code string together

This allows us to fall back to an older style menu should the version of WordPress we're using not support registration of custom menus.

Styling the Menus

In order to cater for all the variations which we've included for our menus, including the additional top right menu and the fallback menu which the placement code generates, I've included a mix of CSS selectors to cover all.
We've essentially got 3 main containers which will house the standard, top right and fallback menus.

  • Standard - #menu
  • Top Right - #top-menu
  • Fallback - .menu

The styles below can be found between lines 100 and 184 of the style.css file

A Quick Wrapup

  1. Create a functions file to register Custom Menus
  2. Create Menus via Appearance > Menus
  3. Insert Menu Placement Code
  4. Ensure menus point to the desired locations or menu names
  5. Ensure HTML being generated coincides with your menu CSS
  6. Ensure Registration Code does not break older WP
  7. Ensure your placement code does not break older WP

Next Up - Dynamic Sidebars Followed by The Loop - Stay Tuned!

Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.