Register Menus Firstly, in your theme’s functions.php, you need to write a function to register the names of your menus. (This is how they will appear in the Appearance -> Menus admin screen.) As an example, this menu would appear in the “Theme Locations” box as “Header Menu”. function register_my_menu() { register_nav_menu('header-menu',__( 'Header Menu' )); […]
Firstly, in your theme’s functions.php, you need to write a function to register the names of your menus. (This is how they will appear in the Appearance -> Menus admin screen.) As an example, this menu would appear in the “Theme Locations” box as “Header Menu”.
function register_my_menu() { register_nav_menu('header-menu',__( 'Header Menu' )); } add_action( 'init', 'register_my_menu' );
And this would make two menu options appear, header menu and extra menu –
function register_my_menus() { register_nav_menus( array( 'header-menu' => __( 'Header Menu' ), 'extra-menu' => __( 'Extra Menu' ) ) ); } add_action( 'init', 'register_my_menus' );
Once you’ve done that, your theme will be almost ready. The last preparation step is to tell the theme where you want the menus to show up. You do this in the relevant theme file. So, for example, we might want our header menu to be in header.php. So open up that file in the theme editor, and decide where you want to put your menu. The code to use here is wp_nav_menu which we will need once for each menu location. So, add this code –
<?php wp_nav_menu( array( 'theme_location' => 'header-menu' ) ); ?>
All you need to ensure is that the theme_location points to the name you provided for your menu in the functions.php code above. (Note that it’s the header-menu being used here rather than Header Menu without a hyphen. header-menu is the name that the code understands, Header Menu is the human-readable version that you see in the admin page.)
To complete the code, you can put your extra menu someplace else. Maybe you want a menu on one of your pages, for example, and you might even want it to be jazzed up a little with a containing DIV of a certain class –
wp_nav_menu( array( 'theme_location' => 'extra-menu', 'container_class' => 'my_extra_menu_class' ) );
So you’d put the above into your Page template, and not only would the menu show up wherever you put it, it’d be styled as my_extra_menu_class so that you can work with that in CSS.
That’s all the background work. To finish, you would simply visit the Appearance -> Menus panel in your site admin. Now, instead of seeing some text suggesting that your theme doesn’t natively support menus, you’ll see some Theme Location options.
You can now use the GUI menu creator on this admin panel to put your menu(s) together. Give them each a name, and then assign a menu to a location with the pull-down options.
(You will see your new navigation choices when you Add a New Menu.).
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.
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:
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.
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.
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:
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.
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.
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>
To 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.
The 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.
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 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.
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:
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.
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.
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.”
Assigning special classes to menu items
Now, 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:
/* 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.
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.