Add Custom Menus to WordPress 3+ Themes

WordPress 3 added plenty of new features – and one of the most useful was the ability to create and add custom navigation or menus to your themes. Whilst they are very simple to implement, they are also extremely flexible, allowing you to add not only pages, categories or posts to your navigation, but also custom links.

Custom menus are a huge bonus for WordPress users. They allow you to easily create a navigation structure, filtering the content and cherry-picking what you want to include. By default you can add pages (and sub-pages) or categories, but you also have the ability to to add links of your own choosing, such as individual posts or external content.

There are a couple of simple steps to add a custom menu to your theme, and you can either do this with a text editor (such as the excellent Espresso, read my review here) or with the built in WordPress Editor, found under the Appearance menu.

Open your theme’s functions.php file and add these lines before the closing ?>

// allow for custom menus
add_theme_support( ‘menus’ );

This prepares the theme to accept the custom menus. Now open your header.php (assuming that’s where you want it to go – more about this later…) and add the function in where you want it to appear:

<?php wp_nav_menu( array( 'sort_column' => 'menu_order', 'container_class' => 'main-nav' ) ); ?>

This tells WordPress a couple of things; to sort the menu to match how you set it up in the Menus panel, and the name of the class (main-nav) that you have given the container for styling. Now, hop over to Appearance > Menus and you’ll see your new custom menu.

WordPress custom menusYou can set it up to automatically add new main/top-level pages as you create them by checking the box next to your Menu Name. On the left, check the pages or categories you want to include and click the Add to Menu buttons. Once they are on the menu, you can simply click and drag them into the order you want, placing sub-menu items by ‘indenting’ them as you drag. You’ll see a dotted border showing you the sub-level each item will appear at. Click the disclosure triangle for each item to change the navigation label and set a title attribute, or remove the link from the menu altogether.

Custom links can be added by entering a URL, setting a label and adding them to the menu, where you then control their placement in exactly the same way.

If you want to add multiple menus to your theme, you need to give them unique IDs, slugs or names. More here at the WordPress codex. There is also a very helpful post here over on Justin Tadlock’s blog.

All you need to do now is style your menu and you are all set to go!

For anyone who is interested, here is a link to the stylesheet for the custom menu on this site: custom-menu stylesheet css file.

other page


  1. Stian

    Finally one that works! Thanks a lot!

    • Stuart

      Glad to help.

  2. Wordpress Tutorial

    Thanks for your post.But i have problem with CSS like container_class and menu class. Can you explane this where it will be puted?

    • Stuart

      In the example shown here, class of the container (container_class) is main-nav. Add a class called .main-nav to your style.css file. Once you write the styling for this element – the menu container, you can style your menu using however you like. You are only adding the container for a custom menu and letting the WordPress functions know that you are going to be adding your own custom menu system. The styling of the menu is up to you and you will just use ul and li tags to target the various parts of the menu.

  3. kaitie

    I’m using the styling .main-nav, however, no style applies to the element

    • Stuart

      Kaitie, it may sound obvious but check that you are using a class, not an ID.

      ‘container_class’ => ‘main-nav’

      • Kaitie

        I did manage to get it to work, it was a cache issue actually, as I’m working with the site live. But I do however have another issue. It seems that the menu doesn’t respond the same way as the rest of the site. It doesn’t react with the ‘page-wrap’ div when expanding, shrinking, and stretching the browser, (you can see what I mean at This might be a really simple CSS solution that I’m not realizing, but if you could help shed any light?

  4. Kaitie

    nevermind, solved that issue too! sorry! thanks for the help and the code!

    • Stuart

      You are welcome. Glad you sorted it out.

  5. kevin

    I got this to work, and I got it styled, but when I try and create a drop down menu, the subpage is added as a regular menu item instead of a dropdown.
    Any suggestions on how to easily get this to enable dropdown functionality?

  6. kevin

    I used this code, and got everything to work fine, except the drop down. Is there something else I can do to add this functionality? When I try and put a page in the submenu, it just goes into the regular nav..

    • Stuart

      Kevin, make sure you are nesting or indenting your sub-menu items as in the image.

      • kevin

        I am. I even tried assigning a parent to the page i wanted in the submenu. Still comes in the main-nav menu.

        • kaitie

          mine is doing the same thing. after the menu was styled, and my client supplied me with more content, i felt it would be better if some of the pages were broken down further into subpages, but when i try to add them to the menu (indented) they appear next to the top-level item rather than under.

        • Stuart

          Please see the custom menu stylesheet I have added a link to at the foot of the post.

      • kevin

        i am indenting them. they appear NEXT to the parent in the menu. not underneath

        • kaitie

          Have you provided help for this issue? I am experiencing the same thing

          • Stuart

            Katie – sorry for the delay, I’ve been really busy! Please see the custom menu stylesheet I have added a link to at the foot of the post. Hopefully, that will help.

  7. kaitie

    okay I’ll take a look at it! no problem, if anyone understands busy, i do. Thank you very much, I’ll see if that fixes it!

It's good to talk!

Your email address will not be published. Required fields are marked *