How to add Navigation Menus to your WordPress Theme

WordPress menus for everyone

WordPress Menus-Title photo of coffee shop menuGlobal navigation menus became much easier to manage when WordPress version 3 added a snazzy menu manager–no plugin or JavaScript required. Every now and then, you may want to use an oldie-but-goodie theme that has not been updated to support WordPress menus. I’ll show you how to easily add menu support to these older themes.

Some old themes still have punch

One day a new friend asked me to do a new simple site design, and needed it in a hurry. She wanted the site to “have a bit of attitude, but not over-the-top.” Immediately, I thought of an older theme I’d used on my own personal site for awhile: Elegant Grunge.

Crash and burn

Still at the coffee shop, I vowed to get her site up and running before she finished her next cappuccino. I searched for, found, downloaded, and installed the Elegant Grunge theme on a new WordPress install. She loved it, and set to work adding a few static pages for an About page, Contact, and some others.

Wait for it

Everything seemed perfect for the new site. We were just getting ready to leave when she asked me how to control the global navigation menu. Chuckling dismissively, I slid back into my chair in front of the laptop and said “No problem! Let me show you how it’s done–you’ll love this!”

WordPress Menus-screenshot of theme locations panel showing a theme with no menu supportAck! As we went to Appearance > Menus, I saw the dreaded “The current theme does not natively support menus…” verbiage in the “Theme Locations” panel. I shook my head and sat back in the chair.

“It won’t be a problem, but it will have to wait until tomorrow,” I sighed.
“Are you sure? You seem hesitant” she challenged.
“Yeah. Yes, definitely, I just… it’s supposed to work a certain way and caught me by surprise.”
“Okay, well, meet me here at high noon tomorrow. If the menus aren’t easy and pretty, it’s no problem–I’ll just use Blogger instead.”

My eyes widened, pulse quickened, face flushed. Blogger?! No way was I going to let my friend go to Blogger! It was time to get to work.

Featured Plugin - WordPress Pop-Up Chat Plugin

No javascript required, no third part chat engine, just fully featured chat right in your own database on your own WP sites - couldn't be easier.
Find out more

We have the technology

A few lines from the 6 Million Dollar Man title sequence came to mind.

“Gentlemen, we can rebuild him. We have the technology.

Better. Stronger. Faster.”

Adding navigation menu support to your theme

Without further ado, let me show you how to add proper menu support to any theme in a hurry.

1. Specifying menu locations in your theme

First, define where you want menus to appear in your theme. Most themes define at least a “Top Navigation” location. Some define “Secondary” and “Footer” locations, as well. These menu location names appear in the “Theme Locations” panel of the “Appearance > Menus” screen, and allow you to later choose which menu content goes in each menu location.

How to add only one location

In your theme’s “functions.php” file, add the following at the bottom.

// This adds just one menu location
add_action( 'init', 'paukai_register_menu' );
function paukai_register_menu() {
    if ( function_exists( 'register_nav_menu' ) ) {
        register_nav_menu( 'header-nav', 'Header Navigation' );
    }
} // end paukai_register_menu()

That tells WordPress you want to use a menu location in one spot. The values passed here are:

  • “header-nav” — the menu location slug you can use behind the scenes
  • “Header Navigation” — the human-readable name describing this location on the Appearance > Menus screen

How to add multiple menu locations

WordPress Menus-Screenshot of Theme Location panel in dashboard

Before moving on with my friend’s site, I figured I should add a second menu location. I didn’t want to be caught unprepared again. There’s always the possibility she might want another menu placed in the footer. To add more than one menu location, change your code to the following. This is used instead of the code above–not in addition to it.

// This adds more than one menu location
add_action( 'init', 'paukai_register_multiple_menus' );
function paukai_register_multiple_menus() {
    register_nav_menus(
        array(
            'header-nav' =>  'Header Navigation',
            'footer-nav' =>  'Footer Navigation'
        )
    );
}

This function “register_nav_menus” takes an array of location slug / description pairs. Save these changes to “functions.php”, reload the “Appearance > Menus” screen, and you should see two menu locations listed.

2. Calling menus in your theme template

Next, you need to update your WordPress theme template files to request these menu locations and put their assigned menus in the places you want them to appear.

Add the header navigation

The header navigation menu–intended to be the global navigation for my friend’s site–would need called in the “header.php” file. You need to find the spot in “header.php” where the current menu method is used so you can replace it.

In the Elegant Grunge header.php file, I found:

<div id="menu">
    <ul>
        <li><a href="<?php bloginfo('url'); ?>"><?php _e('Home', 'elegant-grunge') ?></a></li>
        <?php wp_list_pages('title_li=&depth=1'); ?>
    </ul>
    <div class="clear"></div><!-- clearing div -->
</div>

In most older themes, you’ll find something similar. The function “wp_list_pages” was very commonly used in themes before the new navigation menus came around. For my situation, I replaced all that code with the following:

<div id="menu">
    <?php
    wp_nav_menu (
        array (
            'theme_location' => 'header-nav',
            'container' => false
        )
    );
    ?>
    <div class="clear"></div><!-- clearing div -->
</div><!-- /#menu -->

The “wp_nav_menu” function takes an array of key > value pairs. The two important ones here:

  • “theme_location”–the location slug we used when registering the menu we intend to place here
  • “container”–set to false so WordPress would not automatically wrap the entire menu in a container.
Once you get the hang of this simple tutorial, check out the wp_nav_menus page in the WordPress Codex to see the other optional parameters.

Understanding the “container” parameter

Wait–why did I set “container” to false? After all, the menu is indeed wrapped in a “div#menu,” and I could have the “wp_nav_menu” function do that for us.

At issue here is the clearing DIV just before closing the “div#menu.” If I let WordPress create the “div#menu,” I would not have an opportunity to add that clearing DIV before WordPress closed the “div#menu.” So, I had to open and close the container — “div#menu” — myself.

Featured Plugin - WordPress Infinite SEO Plugin

Fully integrated with the SEOMoz API, complete with automatic links, sitemaps and SEO optimization of your WordPress setup - this is the only plugin you need to help you rank your site number 1 on Google - nothing else compares.
Find out more

Add the footer navigation

Since I also added “Footer Navigation” to the “Theme Locations” panel, I should include it somewhere in my template files–even if my friend doesn’t plan to use it yet. For Elegant Grunge, I edited the “footer.php” file to add this menu location in. The theme has a widget sidebar in the footer, followed by a clearing DIV. I decided to put the footer menu code after that clearing div.

I edited the “footer.php” file  to read as such:

<?php get_sidebar('footer'); ?>
<div class="clear"></div>
<?php
    // begin modifications to add footer menu
    wp_nav_menu (
        array (
            'theme_location' => 'footer-nav',
            'container_id' => 'footer-menu'
        ) );
?>
<div class="clear"></div>
<?php
    // end modifications to add footer menu
?>
<div class="legal"><?php echo get_option("copyright"); ?></div>

I told “wp_nav_menu” to use the menu referenced by the slug “footer-nav,” which we registered before. There was no menu at all in the footer before I came along, so this time I wanted WordPress to wrap the menu in a container DIV (the default) and to give that DIV an ID of “footer-menu” so we could target it with CSS and such.

Preventing output if no menu is assigned

The problem here is the lack of any menu assigned to the footer-nav menu location. If I don’t have any menu assigned to the footer-nav menu location, WordPress will pick up the first menu it can find and sub it in. What I need to do is check to see if footer-nav has a menu assigned to it, and only output menu code if there is a menu.

After adding this conditional test for menu assignment, the code change became:

<?php get_sidebar('footer'); ?>
<div class="clear"></div>
    <?php
    // begin modifications to add footer menu
    if ( has_nav_menu( 'footer-nav' ) ) {
    // a menu is assigned to the footer-nav location
    wp_nav_menu (
        array (
            'theme_location' => 'footer-nav',
            'container_id' => 'footer-menu'
        )
    );
    ?>
<div class="clear"></div>
<?php
} // end if
// end modifications to add footer menu
?>
<div class="legal"><?php echo get_option("copyright"); ?></div>

Building the contents of menus to hook in

WordPress Menus-Screenshot of Menus Theme Location panel with first menu assignedTo check my work, I needed to create a menu using the “Appearance > Menus” interface and hook it up to the new menu locations. I added a menu name of “Global Navigation,” clicked “Save Menu,” and then added a number of pages in primary, secondary, and tertiary positions.

Once I did this, I was able to select “Global Navigation” for our “Header Navigation” menu in the “Theme Locations” panel. I reloaded the page to see what we would get.

WordPress Menu-Screenshot of header menu without proper CSSThe results were not encouraging! My menu items were all stacked vertically, and this messed up the site’s logo and tagline, as well. So much for a simple, quick site, right?

I didn’t panic, though, as I knew right away some simple CSS changes would fix things up. This is the kind of hassle we used to deal with all the time before WordPress added the navigation menus. I decided to copy the CSS rules from the 2011 theme and modify them to meet my needs.

Styling menus for proper display

To make your new menus display properly, you need to add some rules in your “style.css” file. For Elegant Grunge, I copied the styles from Twenty Eleven theme first, then modified from there.

The menu container element

The Twenty Eleven theme uses an ID of “access” on the menu’s containing element. In the Elegant Grunge theme, the menu’s containing element is “#menu,” so in the style rules I change “#access” to “#menu” in all spots.

Combining two different styles

As soon as I made the “#access” to “#menu” change in the style rules, the menu looked a lot better. However, it was tucked way up in the upper left corner instead of under the site logo and such. I had a look at Elegant Grunge’s original style rules for #menu to see what was the matter.

Theme authors can position elements in a variety of ways. When combining styles from two different themes, you need to look at differences between positioning and sizing declarations. Key properties to compare and combine are:

  • position / top / bottom / left / right
  • width / height
  • padding / margin
  • float / clear
  • display

In my case, I needed to comment out some of the Twenty Eleven styles on #menu and #menu ul, then add in a few of the elements as Elegant Grunge originally styled them. That’s all explained in the following downloadable CSS snippet.

Note: The downloadable is an excerpt of the hybrid Elegant Grunge / Twenty Eleven style.css file, reflecting changed styles to make the dropdown menu work.

The downloaded style file makes it all work nicely. Experiment with the CSS from there to get different looks. Current page highlighting and other effects are possible, purely in CSS.

Adding Custom Classes per Menu Item

Sometimes menus can get pretty crowded. You’ve probably seen some horizontal menus that could stand some trimming. With our current styles, a menu near the right side of our page will open further to the right and potentially off screen. If you have this problem, you can fix it by adding a special class for those right-most menu items.

Advanced menu options

On the Appearance > Menus screen, click the “Screen Options” tab near the top. When this pops down, put a check in the option for “CSS Classes.”

WordPress Menu-Screenshot of Menu screen options panel

Assigning special classes to menu items

WordPress Menu-Screenshot of menu item with additional custom class fieldNow, click the disclosure triangle for any menu item. You’ll see a “CSS Classes” field you can optionally fill in. If you have menu items that open too far to the right, try this:

  1. Add the class “leftlevel3.” My intention was to make 3rd-level dropdowns open to the left of their parent menu instead of the right.
  2. In your style file, add a suitable class and declarations. You will need to experiment to get the right placement. For my Elegant Grunge theme, I added the following:
 /* special class manually applied to open submenu left */
 .leftlevel3 {
     right:375px;
 }

Note the more correct way of positioning the entire 3rd-level dropdown would be to position the <ul> element containing all those 3rd-level list items. Unfortunately, we cannot add classes to the <ul> itself in the Menus interface.

Menus the way they should be

If you followed all that, you should end up with WordPress Navigation Menus available for use–even in your older themes. The styling might take a bit of debugging, depending on how well the CSS was coded in your original theme. Just think, though: once you get it working the way you like, you won’t have to worry about again! You or your clients can simply use the Appearance > Menu screen to easily make menu changes.

What do you have to say?

Did you understand this tutorial? Are there any themes you know of that need this treatment? Let me know what you think, and please ask if anything is unclear here.

Featured Plugin - WordPress Newsletter Plugin

Now there's no need to pay for a third party service to sign up, manage and send beautiful email newsletters to your subscriber base - this plugin has got the lot.
Find out more

Credits

Tags

Comments (5)

  1. Thanks for this – I’ve managed to create my own top menu bar in 2011! Hooray!

    I notice, though, that the menu items are positioned further to the left in this new menu than “home” was in the default menu. Looking at the page source, I see that the default 2011 menu is wrapped in div tags:

    Main menu

    Home

    and the new menu isn’t:

    Main menu
    bbc
    amazon

    I’m struggling to see which part of the css I should change to push the new menu items to the right a bit.

  2. This is pretty cool, but I’m having trouble adapting it to what I’m doing. I want to transplant a menu from a premium them I have to another them, along with its css styles. I was going to past the menu code from the original theme into the header of the target theme, and copy the css to the bottom of the target style sheet, but I can’t figure out what to put in the functions file. The beginning of the menu code is this:

    I don’t know what names to insert in your code, or if something else should be done. Any suggestions?

    • Of course the code didn’t get preserved in that comment. Here it is with the angle brackets removed:

      div id=”secondary-menu”
      div class=”container”
      ?php do_action(‘et_secondary_menu’); ?
      nav id=”second-menu” class=”clearfix”

  3. Hello! I know this is a very old post! but i’m dealign with an old theme and need to add wordpress 3.0 navigation style but i’m not code savy… can this be done with a plugin?
    Thanks!

Participate