WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Lets say we are displaying a few family trees. We are currently on the family tree top-page,and we need our list to look like this:

Family Trees

  • The Smiths
  • The Joneses
  • The Does

When the user clicks the Smiths, we want the list to look like this:

The Smiths

  • The Smiths
    • Dave
    • Steve
    • Dolly
  • The Joneses
  • The Does

And when a user clicks on Steve, we want the list to also look like this:

Dave Smith

  • The Smiths
    • Dave
    • Steve
    • Dolly
  • The Joneses
  • The Does

So, we need to display a list of all subpages and siblings of the current page, as well as all siblings of every step in the hierarchy.

Any ideas?

share|improve this question
Hi @Joseph Carrington: What post type are these? Are they Pages, or custom post types? Also, do you want to load all data when you load the page and use jQuery+CSS to expose the ones you want, or do you want to use jQuery+AJAX to load the subpages on demand? (If you have lots of these the latter may be your only viable option.) – MikeSchinkel Oct 19 '10 at 4:33
Well, ideally I would be using PHP and as many built in WP functions as possible. I don't see the need to involve javascript at all. – Joseph Carrington Oct 19 '10 at 15:58
Sorry, for some reason I never saw your response. For future reference it's because you didn't @reply me so the site never notified me of your comment. Can you answer what the different menu items are; Pages or Custom Post Types, Categories, Tags, etc? – MikeSchinkel Nov 13 '10 at 0:02

What you write reminded me to some plugin / widget I know of. It's related to Silo Web Design and the plugin is the Silo Widgets Plugin For WordPress. In SemPro you can make use of inline widgets to display something like that within posts.

share|improve this answer

This was a pretty decent plugin for displaying a flexible list of pages last time i tried it(no need for it myself)..


If anything, you should be able to look to that plugin for some ideas and inspiration on how to tackle it..

share|improve this answer

I actually had to do this once. You can do it without a plugin and without javascript. You might have to tweak it a little to work exactly as you need it but it should give you the right idea; displaying parent pages and their children etc.

Here is the tutorial I used: http://www.svennerberg.com/2009/02/creating-a-submenu-in-wordpress/

share|improve this answer

Forget plugins, i had the same problem and plugins created a whole raft of mess and too many db calls.

This code will do the business for you - for ease of use, stick it in a content part and include it like so:

get_template_part( 'subnav', 'pagename' );

The problem is, you already know your children, and you know your parents. I tried using the wp-list-pages function , with echo set to false andincluding id's but that got a little messy. This solution isnt perfect but it's far cleaner than using a plugin or two.

In a nutshell - you want the absolute top parent id, then you want to get all the children of the current posts ancestors:

function get_top_id($id){
   $parents = get_post_ancestors( $post );
   return $parents[count($parents)-1]; 

function get_sub_pages($id){

    global $post;

    // get the ancestors for this depth
    $parents = get_post_ancestors( $post );

    //add the post id to the list in order to get the children
    array_unshift($parents, $post->ID);

    //reverse the order of the array
    $parents = array_reverse($parents);

    // specify to get all children of the top level parent
    $args = array( 'child_of' => $id); 

    if($subPages = get_pages($args)):

        // start at the first  $parents array key
       $curParent = 0;
       $childList = '<ul>';

       if($id == $post->ID) $class = ' class="selected"';
       $childList .= "<li" . $class ."><a href='". get_page_link( $id )."'>Introduction</a></li>" ;

       foreach( $subPages as $page ) :

            // only add the item if:
            // a: the pages parent is in the ancestors array

            if(in_array($page->post_parent, $parents)){ 

                // get the key of the page parent within the $parents array 
                // this helps us check if we are going to a deeper/higher level
                $pageParent = array_search($page->post_parent, $parents);

                if($curParent != $pageParent){

                    // if we are going deeper, add a new list for the children
                    if($pageParent > $curParent){
                        $childList .= '<ul>';

                    // if we are going higher, check how many depth changes                        
                    if($pageParent < $curParent){                            
                        $depthChange = $curParent - $pageParent;

                        // close off all the children of higher depths
                        while($depthChange > 0){
                            $childList .= '</li></ul>';
                            $depthChange --;

                    // set the new parent level
                    $curParent = $pageParent;                        

                $class = '';
                if($page->ID == $post->ID) $class = ' class="selected"';
                if($page->ID == $post->post_parent) $class = ' class="parent"';

                // leave off the trailing <li> in case there are children to be added to this
                $childList .= "<li" . $class . "><a href='". get_page_link( $page->ID )."'>". $page->post_title . "</a>" ;



       $childList .= '</ul>';


    return $childList;

// get the absolute top level parent of this page
$topID = get_top_id();

// if no parent, we are ar the top
if(!$topID) $topID = $post->ID;

echo get_sub_pages($topID);

This code also adds the class 'selected' to the current post, and 'parent' to the current post parent within the list.

Hope that helps someone!

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.