In usability we trust

UX and all things web

Creating a Submenu in WordPress

For a project I’m currently working on I wanted to create a submenu that included the parent page as well as the supbages. I just wanted to display the submenu only if the parent page had subpages. Searching the WordPress Codex and googling for a solution I couldn’t quite find an example that took all these factors into consideration so I had to figure it out myself. Here’s the approach I came up with.

Checking if the page has subpages

I searched in vain for a method to determine if the current page has any subpages or not. I first assumed that there would be a has_subpages() method, but so far I haven’t found any. Lacking that, I came up with a very crude way of checking it. I explicitly had to try to fetch all the subpages with the function wp_list_pages() and then check if it returned anything. It’s not pretty but it works.

$children = wp_list_pages('&child_of='.$post->ID.'&echo=0');
if($children) {
    // This page has subpages

Checking if it’s a parent page or a subpage

The next thing I had to figure out was how to check i the current page is a parent page or a subpage. That’s done with the following code.

if(is_page() && $post->post_parent) { 
    // This is a subpage
} else {
    // This a parent page

Fetching the submenu

Now I needed a way to fetch the subpages. This is done with the wp_list_pages() function. The tricky part about this is that there’s no way to get both the parent page and the subpages in the same call. So therefor we have to call the function twice. The call also looks a little different depending on if we’re on the parent page or on the subpage.

if(is_page() && $post->post_parent) {
    // This is a subpage
    $children = wp_list_pages("title_li=&include=".$post->post_parent ."&echo=0");
    $children .= wp_list_pages("title_li=&child_of=".$post->post_parent ."&echo=0");
} else if($has_subpages) {
    // This is a parent page that have subpages
    $children = wp_list_pages("title_li=&include=".$post->ID ."&echo=0");
    $children .= wp_list_pages("title_li=&child_of=".$post->ID ."&echo=0");

There are other ways of doing this, but the benefit of this approach is that we automatically get class="current_page_item" on the list-item that represents the page that we’re currently on. That’s handy if you want to style that item in any particular way.

Outputting the HTML

The last step is to output the actual HTML. I’ve chosen to output it as an unordered list.

<?php // Check to see if we have anything to output ?>
<?php if ($children) { ?>
<ul class="submenu">
    <?php echo $children; ?>
<?php } ?>

Putting it all together

Now it’s time to put all the pieces together. Just put this code in your page template one of the pages in your template, like for example page.php or sidebar.php and you’re good to go. These pages are located in /wp-content/themes/your-theme/.

$has_subpages = false;
// Check to see if the current page has any subpages
$children = wp_list_pages('&child_of='.$post->ID.'&echo=0');
if($children) {
    $has_subpages = true;
// Reseting $children
$children = "";

// Fetching the right thing depending on if we're on a subpage or on a parent page (that has subpages)
if(is_page() && $post->post_parent) {
    // This is a subpage
    $children = wp_list_pages("title_li=&include=".$post->post_parent ."&echo=0");
    $children .= wp_list_pages("title_li=&child_of=".$post->post_parent ."&echo=0");
} else if($has_subpages) {
    // This is a parent page that have subpages
    $children = wp_list_pages("title_li=&include=".$post->ID ."&echo=0");
    $children .= wp_list_pages("title_li=&child_of=".$post->ID ."&echo=0");
<?php // Check to see if we have anything to output ?>
<?php if ($children) { ?>
<ul class="submenu">
    <?php echo $children; ?>
<?php } ?>


I think that WordPress is an absolutely awesome CMS/Blog engine, but it do lack some handy methods. Fortunately it’s almost always possible to create workarounds. I hope that you will find this useful in your own WordPress Template. Don’t hesitate to tell me if you have a smarter way of doing this.


  1. You mention adding this to the template file, where in the template file do you add this? and by template file i presume you mean “template.php” in admin>includes?

  2. Hi Matt,

    No I mean one of the files that makes up a template, like for example page.php or sidebar.php in /wp-content/themes/your-theme/. Sorry for being unclear about that. I’ve updated the article accordingly.

  3. Hey,

    I think this is missing a <?php opening statement. And even when I add that it doesn’t appear to work.

  4. Tim: Your’e absolutely right Tim! There was a missing php opening statement. On top of that there was also a missing php closing statement. I’m really sorry about that. I have now corrected the code in the example so please try it again.

  5. Dukessa: That’s sweet! If you’re not into building your own templates, that’s an excellent option. Thanks for the tip!

  6. hey dude,

    thx for the nice script! i’m wandering though! my navigation is split in 2, mainNav is in the header.php and i’m calling your nice code (my subNav) into my index.php like that:

    the results are, when i click on a page in the mainNav that has subNav pages (lets say 3 for example) i’m seeing actually 4 pages (the mainNav page as a subNav page and my 3 subNav pages) and that’s fine, but.

    my 1st question is how could i rename the the mainNav page name that is automaticly shown in the subNav?

    and, my 2nd question (the most important) is how can i get the mainNav li.current_page_itme {} to remain active when i’m clicking on another subNav pages (that is not pulled from the mainNav)?

    thanks so much


  7. oh,

    sry for bothering! i just found the answer to the 2nd question. i needed to add the following code to my CSS.

    .mainNav li.current_page_ancestor {}

    uuppps :)

  8. Just thought to let you know that an alternative way to do this is to use the code from the sidebar of the K2 Theme. Just strip away all the other stuff and you are left with a very nice piece of code and it’s a simple thing to make the heading clickable also if you want.

  9. Linda: Cool! I will definitely check that out. Thanks for the tip!

  10. Very interesting post, I love finding a good quality blog thats not full of rubbish. I would love to do a link exchange.

  11. Super script: Nice and well explained! Love that!
    One small thing: you mention:

    // Check to see if we have anything to output

    And that particular text shows up in my WordPress project :-) Because it is outside a PHP tag…
    Tanks for your blogpost!

  12. marnix bras: Thanks for noticing! I’ve corrected the example.

  13. Hi

    Great post, pretty much exactly what I was looking for, thanks for that!

    I am very new to both wordpress and php so I’m sorry if this is a stupid question but I’m stuck
    The code that is output from this php looks something like his for each list item:

    Sub Page1

    Is it possible to insert a span within the anchor somehow? so the php would output something like this?

    Sub Page1

    Or would this make things complicated?

  14. sorry about the links in that last comment

    I basically want it to output something like this (ignore the extra spaces)

    Sub Page1

    hope it works this time

  15. Sorry for the flooding.. managed to insert a span in the anchors by using link_before and link_after like so

    if(is_page() && $post->post_parent) {
    // This is a subpage
    $children = wp_list_pages("title_li=&include=".$post->post_parent ."&link_before=&link_after=&echo=0");
    $children .= wp_list_pages("title_li=&child_of=".$post->post_parent ."&link_before=&link_after=&echo=0");
    } else if($has_subpages) {
    // This is a parent page that have subpages
    $children = wp_list_pages("title_li=&include=".$post->ID ."&link_before=&link_after=&echo=0");
    $children .= wp_list_pages("title_li=&child_of=".$post->ID ."&link_before=&link_after=&echo=0");


  16. Hi, Love the work you’ve done on this little submenu code, it was a piece of cake to add to my custom theme, however I’m just wondering how it would be possible to have the submenu output on a single horizontal line? (eg submenu1 | submenu2 | submenu3 | submenu4)


  17. @Tim: Your best bet is to use CSS to style the unordered list so that it’s horizontal. A now old, but still excellent article on how to do this is CSS Design: Taming Lists at A List Apart.

    Hint: Try .submenu li {display: inline} in your CSS.

  18. Can someone help me with this? I have lots of articles and I want to display them under different parents. Here is my question:

    1. I want parent pages to be formatted differently than child page list

    For example in the link here:

    My parent page is called “Feature-Length Articles” [which is NOT a link and is formatted differently]

    Now I want to show all the children pages as links [] list with publish date.

    Thanks for all the help.

  19. What about having a completely seperated and with the submenu only showing when a main page has subpages, set the submenu still shows when a subpage has been clicked.

    That sounds much more difficult and is what I’m current working on.

  20. WordPress scrubbed my custom divs so that post didn’t make sense. Here it is again:

    “What about having a completely separated [div id=”menu][/div] and [div id=”submenu”][/div] with the submenu only showing when a main page has subpages, yet the submenu still shows when a subpage has been clicked.

    That sounds much more difficult and is what I’m current working on.”

  21. I love your script, is what a need, but all the sub-pages are showin in the search page, how can a fix this?

  22. Just wanted to thank you for this, this works perfectly and was exactly what I was looking for.
    Thanks again.

  23. thanks, great post, works great!

  24. Thanks! This saved me heaps of time and worked straight out of the box. You’re a champion :)

  25. Thank you. Worked for me first time.

  26. Thanks for the hack! Worked perfectly.

  27. Thanks, you helped me allot!

  28. Like many others, you’re help saved the day and I really appreciate you taking the time to share the knowledge!


  29. I really like your writing style, its not generic and extremly long and tedious like a lot of blog posts I read, you get to the point and I really enjoy reading your articles! Oh, and merry Christmas!

  30. ID.’&echo=0′);

    if ($children) { ?>

    I found this shorter, simpler version you might like.

  31. This has worked perfectly for me, thanks! It is exactly what I have been searching for all day – after trying a lot of other suggestions thatall failed! Wish I had found this first! lol

  32. Thanks so much for this Gabriel. I’ve used a few different PHP snippets for secondary menus on various WordPress sites, but none of them were able to highlight the parent menu item when that page was active. But yours fixes that. Really appreciate it.

  33. Hi!

    I a newbie at PHP and wordpress. I used you script and it works great!

    Now I have a problem though. How do I add a menulevel 3? So topmenu -> submenu ->subsubmenu

    It works displaying the subsubmenu but clicking the subsubmenu the other pages in the menu dissaper.

    Also i cannot figureout where i edit the for the subsubmenu.

    Anyway helt would be deeply appriciated.


  34. EDIT: Also i cannot figureout where i edit the UL for the subsubmenu.

  35. Hello Gabriel Svennerberg, I am new in wordpress and I’m confused for using this now..
    maybe this is weird question, but want to ask, where I can put the code that you have written it? thx for the answer.

  36. how to write main menu to submenus and sub-sub menus

  37. thanks for the code, it’s EXACTLY what I needed!

  38. Great post. Over a year old and still useful. Thank you!.

  39. Hey There. I found your blog using msn. This is a really well written article. I?ll make sure to bookmark it and come back to read more of your useful information. Thanks for the post. I will definitely return.

  40. Thanks, It really worked…

  41. Hi, This looks exactly what I am looking for, however I am completely alien to PHP.
    I understand I have to put the code within the page.php file, but I am not sure where exactly it goes. I have tried inserting it into various places but it doesn’t seem to work.

    Can somebody please let me know exactly where I place the code?

    And also if there is any other amendments that need to be done in any other files css etc?

    Thank you in advance.

  42. @Sarah,
    The example sais use it in page.php, altho i do not know if it is theme dependant
    When you look at page.php u see a reference to navigation.php
    “” in my case.
    Try adding the code WITHIN the menu-div on Navigation.php as that seemed to work for me.

    If experiencing trouble drop me a mail @

  43. hi it is the great thing that we see here it give us the idea about the submenu

  44. Hi Gabriel,

    Many many thanks for this – it works wonderfully on my code. However, not being a php savvy ( I am just a designer) I encountered a problem, wondering if you might help.

    i am using custom templates on some of my subpages, and it seems your code does not recognizes them as subpages, so on those pages the submenu is not fetched. However, on the other pages using the default template (page.php) the submenu works great, including showing the link to the customized subpage….do you know how i could fix this?


  45. Your code helped me to accomplish something I needed to do on a custom page template. Thanks.

    Do you know how I could edit this code to have it also output the post thumbnail for each of the pages in the list? I’m using the post thumbnail / featured post option built in to WordPress 3.1.

  46. Perfect!!! thanks mate.

  47. Thanks ! This very helped me. :-)

  48. If you want get submenu of menu WP, you can use this plugin:

  49. Hi Gabriel! Even though I’m swedish too, I’ll keep it in english.

    First of all: Thanks a lot!

    I’m doing a web site for a friend who’s starting a new tattoo studio. There are two artists there and I’d like to put it like this:

    Artists (parent)

    Artist #1 (child of Artists, parent of Tattoo style #1 & #2)

    Tattoo style #1 (child of Artist #1)
    Tattoo style #2 (child of Artist #1)

    Artist #2 (child of Artists, parent of Tattoo style #3 & #4)

    Tattoo style #3 (child of Artist #2)
    Tattoo style #4 (child of Artist #2)

    It works as is, but I want to hide the Tatto Styles when I’m on the Artists page. I only want to show one generation och children at a time, which means that when I go to the page Artists I want to show it’s children only: Artist #1 & #2. When I click on Artist #1 I only want to show it’s children, not Artist #2s children.

    Any thoughts?

  50. And also, when I click on Tattoo style #1, #2, #3 or #4 it’s parent disappears. I Only get the main parent, Artists and the two children belonging to the middle parent (Artist #X) which has disappeared. The other middle parent is also missing.

  51. This stumps me. I’ve used most of the day trying to find an example that says: “That’s easy, here’s what you do…” but all I find are articles like these
    And your own article.

    It should make me angry – but I am more amazed. Separate submenus is practially in every website I develop – and you mean to say that the most used CMS system in the world doesn’t have a simple startLevel parameter in the wp_nav_menu function?

    Please tell me I am wrong!

    • A startLevel would be amazing. I have no clue how this can possibly be missing – it was much easier with list_pages, but somehow someone decided we didn’t need that kind of functionality anymore. Fools.

      I’ve been searching on/off for weeks for the right way to make relative childmenus in wordpress 3+, without luck.

      I am out of options.

  52. This was perfect. Just the kind of script I was looking for. Your generosity is much appreciated.

  53. Just an update to your post.

    Function explained and lots of examples on wordpress:

  54. This is great. Thanks! I was wondering if you could help me figure out where to put the style tags. I’ve wrapped the entire code in a div tag, which works for the child pages, but I’d like to use my h2 style for the parent page, but I can’t figure out how to include that. Thanks so much!

  55. Brilliant, just what I was looking for. You saved my site!

  56. Mohamed Shafiee

    April 7, 2012 at 10:13 am

    Hi. This is Mohamed Shafiee here. Just wanted to share this because I want to make your lives easier with wordpress. My problem was displaying a list of menu items for a specific page or category. The menu was created by using wp_nav_menu(). I was able to achieve this, but it accesses the mysql database as I’m not that experienced with wordpress yet. It works like a charm. Here is the code:

    function get_sidemenu() {

    $page_id = @$_GET[‘page_id’];
    $cat = @$_GET[‘cat’];

    $id = $page_id . $cat;

    $sql = “SELECT caption, guid, post_id, menu_order FROM ((SELECT CONCAT(id, ‘-‘,(SELECT ‘post_type’)) AS pid, post_title AS caption, (SELECT ‘post_type’) AS type, guid FROM wp_posts) UNION (SELECT CONCAT(term_id, ‘-‘, (SELECT ‘taxonomy’)) AS pid, name AS caption, (SELECT ‘taxonomy’) AS type, CONCAT(‘./?cat=’, term_id) AS guid FROM wp_terms)) posts INNER JOIN (SELECT post_id, CONCAT(SUM(IF(meta_key=’_menu_item_object_id’, meta_value, 0)), ‘-‘, GROUP_CONCAT(IF(meta_key=’_menu_item_type’, meta_value, ”) SEPARATOR ”)) AS object_id, SUM(IF(meta_key=’_menu_item_menu_item_parent’, meta_value, 0)) AS parent FROM (SELECT post_id, meta_key, meta_value FROM (SELECT * FROM wp_postmeta WHERE post_id IN(SELECT post_id FROM wp_postmeta WHERE meta_key=’_menu_item_menu_item_parent’ AND meta_value=(SELECT meta_value FROM wp_postmeta WHERE post_id=(SELECT post_id FROM wp_postmeta WHERE meta_key=’_menu_item_object_id’ AND meta_value=[id]) AND meta_key=’_menu_item_menu_item_parent’))) k WHERE meta_key=’_menu_item_object_id’ OR meta_key=’_menu_item_menu_item_parent’ OR meta_key=’_menu_item_type’ ORDER BY post_id ASC) menu GROUP BY post_id) postmeta ON = postmeta.object_id INNER JOIN (SELECT id, menu_order FROM wp_posts) pst ON ORDER BY menu_order;”;

    $sql = str_replace(‘[id]’, $id, $sql);

    $res = mysql_query($sql);

    $html = ”;

    while ($arr = mysql_fetch_array($res)) {
    $html .= ‘‘ . $arr[‘caption’] . ‘‘;
    $html .= ”;

    return $html;


    Put the function in functions.php and use it where ever you need it. The SQL statement is not optimized yet coz I’m running out of time. Do you guys have any comments about this? If you do please email me. My email address is

  57. Mohamed Shafiee

    April 7, 2012 at 10:16 am

    I believe that wp_nav_menu should create a menu that can be accessed when creating themes don’t you think? I wouldn’t have had this problem if that was available.

  58. Thanks this was exactly what I needed, I couldn’t find a script for this anywhere!

  59. You have to check the var $post->ID
    If its not higher than 0 it can be a 404 Page.

    if (!$post->ID > 0) $has_subpages = false;

  60. Thank you very much, it works perfectly and help me a lot!

  61. Doesn’t work for me. Made my navbar disappear.

  62. How do we put the code in wordpress ?
    I am a novice
    Team – Equinox e Services –

Leave a Reply

Your email address will not be published.


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>