WordPress: Dynamic Sub-Page Navigation

The more and more I study the WordPress architecture, the more and more convinced I become that WordPress is a great choice for use as a feature rich Content Management System (CMS). Basically, WordPress can be used, not only as a blog platform, but as software to manage the content of any website, with or without a blog. Because WP added the ability to use “Pages” to hold relatively static content, and because WP includes functions to call and display the content of those pages just about any way you can think of, all it takes is a good WordPress theme to get the job done.

But where WordPress lacks as a CMS is the ability to further exploit the sub-page system. Not so much in their use, but in their application to the actual website design.

However, this plugin did wonders for people looking to take advantage of the hierarchal structure of pages and sub-pages by allowing only the “parent” pages to be displayed on the homepage. And if a “parent” page has children, and that page’s link is clicked, then the child pages will “fold” down, displaying “deeper” options (much like the features of the more mainline CMS out there).

But There’s a Problem

I’m not here to just give props to a cool plugin. You see, I had a client who wanted the original “parent” list across the top of the page (just under the header image) and when one of the “parent” page links was clicked, he wanted the “sub-pages” to display as a list in the sidebar. As far as I could tell, there was no way to do that with the Fold Page List plugin. So, I went searching. I promise, if I could find the original website I got this from, I’d give a link. As it turns out, I can’t find it. Sorry :-)

First thing to do is just list your pages. Be sure to make it top-level only!

<?php wp_list_pages('title_li=&depth=1'); ?>

Then, I used the code I found (with a few modifications, I’m sure):

global $wp_query;

if( empty($wp_query->post->post_parent) ) {
$parent = $wp_query->post->ID;
} else {
$parent = $wp_query->post->post_parent;
} ?>
<?php if(wp_list_pages("title_li=&child_of=$parent&echo=0" )): ?>
<div id="submenu">
<?php wp_list_pages("title_li=&child_of=$parent" ); ?>
<?php endif; ?>

Without getting too technical, I’ll explain roughly what all that means.

if( empty($wp_query->post->post_parent) ) {
$parent = $wp_query->post->ID;
} else {
$parent = $wp_query->post->post_parent;

This code checks to see if the current page (the active page) as a parent. If it does NOT have a parent … it assigns the current page ID as the “parent”. If it DOES have a parent, it assigns the parent ID as the “parent”. The reason this is necessary is for top-level parents. If we simply used the parent ID to assign the “parent”, then if a top-level parent was active, the “parent” variable would be empty and we wouldn’t get our sub-page list.

<?php if(wp_list_pages("title_li=&child_of=$parent&echo=0" )): ?>
<div id="submenu">
<?php wp_list_pages("title_li=&child_of=$parent" ); ?>
<?php endif; ?>

This last part is pretty simple. All it checks for is IF there are any sub-pages (in a very rudimentary way). If it does have sub-pages, then it lists them (along with a title and some div wrappers for style).

One Limitation

I didn’t spend too much time doing research on this, but as far as I can tell, this only works 2 levels deep (top-level and 2nd level). If you have 3 levels of sub-pages, this won’t work (or at least won’t work like it’s supposed to). Sorry, but all I needed was 2 levels, so that’s all I developed it for :-)

Download the Source

Click Here to download the source for this script

So, if you are looking for a quick and dirty way to use WordPress as a CMS, this little bit of code can go a long way. I’ve used it several times since the time I developed it, and I plan on using it many times in the future!

Next week, I’m writing a tutorial on how to do the same thing we did here, but with categories and sub-categories. Don’t miss it!


  1. says

    That is great and what I need for an up and coming website using WP.

    I remember mentioning in a previous blog that this was one of the very few limitations for WordPress to become a fully top notch CMS system.

    Looks like my dreams have come true, thanks :D

  2. says

    I run a website on WordPress (ShowBizRadio.net), and tried using WP as the CMS. Unfortunately, after adding around 750 pages, WP couldn’t cope. The Manage Pages functionality bogged down. I had to raise my server’s memory limit for PHP. And adding new pages started taking longer and longer, to the point that the browser would timeout while working. So while I *love* the idea of using WP as a full CMS for pages plus blog posts, I don’t think it is there yet. Hopefully a few releases from now the memory management of the PAges system will be much improved.

  3. says

    Your timing, my friend, is awesome :). A client of mine asked for the very same thing. With a little variation and experimentation, you saved me quite a bit of headache.

    Keep up the excellent work Mr. Rice,


  4. says

    If I’m not mistaken, I believe the widget that I’ve written replicates the same functionality as your technique. Plus, my widget will display at least a page that is three levels below the main page (I have an example at my site).

    For those interested, you can check it out here:

    Subpages Widget

  5. Axel says

    Hi Nathan,

    sounds exactly like what I need. If I understand it right, it turns the menu-itmes of a top-level navigation in the header into a drop-downs. Is that right? I’m an absolute beginner with WP and I’m not sure where to put that could. Does that go into header.php?

    cheers, Axel

  6. says

    Grazie Nathan, (thanks)
    Dopo settimane (weeks) di prove e mal di testa (headache) questa è la soluzione a tutti i miei problemi (sounds exactly like what I need).

    Grazie. Renzo B,

  7. Nelson says

    Great post, one suggestion in case anyone is having problems with this not showing up with custom plugins, just precede the entire block with:


    I’m new to WordPress, but I came across that pretty easily. Thanks again!

  8. says

    I’ve been searching in vain for a way to do exactly what this article describes, and I found a snippet right in the WP codex for it. It’s very similar to the code you’re using Nate and in fact it looks great throughout the theme except for one caveat… it goes kaput if I load up a 404 page or an erroneous search results page (entering a term I know won’t produce any results). This is regardless of whether I try the script you posted or the one on the codex. Has anyone else actually tested this on those page templates by chance?

    I’m going nuts trying to figure out this bug. The templates I’m using are pretty much just like those of the default theme, and do nothing more than call the header as any other page would. Stands to reason if it works on every other page it would work on those two, but it isn’t for me… :(

  9. Reino says

    This is a great way! Simple but effective, i’m searching for this for hours! There are a lot of plugins like this, but none of them are showing the subpages when your on a subpage. This one does! Thank you very much!

  10. Rob Schumann says


    I’m the author of the Fold Page List plugin mentioned in your article. The ability to determine a complete ancestral hierarchy for any page in the site has been included since the beginning, just not documented.

    There is though now a brief description of how the _wswwpx_page_get_ancestor_ids internal function may be used to obtain an ancestral array (of ids), and that this then provides you a means of building multi-layer page menus without any depth limitation within your wordpress site.

    The only proviso would be that you need to call Fold Page List once for each navigational menu you need to include… but that’s also true of wp_list_pages.

  11. exizt says

    Thank you very much for your post. It was very helpful, especially since there were no examples given on the plugin page.


Leave a Reply

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