Dynamic Subnavigation

February 20th, 2008
Dynamic Subnavigation

When it comes to subnavigation, Wordpress can get sort of quirky. Subnavigation contains links to the child pages of a top level page.

For example, on my website the five top level pages are those linked in the header above this post. Each section's subnavigation (if it exists) is displayed in the sidebar whenever you browse there and those links will stay there as long as you are in that specific section.

By default, if you use the regular wp_list_pages template tag, it will print out ALL page links in a little hierarchy, as you may have noticed. But with a little tweaking to the function, you can achieve the same effect as shown on my site.

The Code Snippet

Using a little trick I found on the WP Codex, I was able to list only the child pages within a certain section and make them stay static:

Note: This will only work with Wordpress 2.5!

<?php if($post->post_parent)
$children = wp_list_pages(array(
    'depth' => 1, 
    'show_date' => '',
    'date_format' => '',
    'child_of' => $post->post_parent, 
    'exclude' => '',
    'title_li' => '', 
    'echo' => 0,
    'authors' => '',
    'sort_column' => 'menu_order, post_title'));
else $children = wp_list_pages(array(
    'depth' => 1, 
    'show_date' => '',
    'date_format' => '',
    'child_of' => $post->ID, 
    'exclude' => '',
    'title_li' => '',
    'echo' => 0,
    'authors' => '',
    'sort_column' => 'menu_order, post_title'));
if ($children) { ?>
<ul><?php echo $children; ?></ul><?php } ?>

You can just drop this snippet right into your sidebar without having to edit it at all. I must note that you can NOT use this code in a sidebar widget, it must be added directly into your sidebar.php code.

As you can see, it uses the built in "wp_list_pages" function with a little twist. In layman's terms, it is telling Wordpress to list the children of the current page's parent (child_of=$post->post_parent) or if that doesn't apply (else statement) then list the current page's children (child_of=$post->ID).

Subpages of Subpages

One thing to note is the depth parameter value. Right now it is set to 1, which means it will show only top level pages as opposed to all of the subpages in the list (which is a paremeter of 0). This also means that if you have a subpage within a subpage then the subpage's subpage will not display unless on the first subpage. Whoa... O_o

For example, let's say in my "About" section I have a subpage named "Interests". Under this "Interests" subpage I have another subpage named "Movies". I only want the link to "Interests" to display when anyone is on the "About" page and NOT "Movies" unless the visitor is actually on the "Interests" page itself. That is what a depth parameter of 1 can allow. :)

See more explanations of other parameters on the WP Codex.

Conditional Links

The only bits I added to that code for my own site were extra links to pages outside of my Wordpress blog. For example, I wanted to link my Trading Post in my "About" section's subnavigation. Since the above code will only print out Wordpress pages, I used some additional Conditional Tags to modify it:

<?php if($post->post_parent)
$children = wp_list_pages(array(
    'depth' => 1, 
    'show_date' => '',
    'date_format' => '',
    'child_of' => $post->post_parent, 
    'exclude' => '',
    'title_li' => '', 
    'echo' => 0,
    'authors' => '',
    'sort_column' => 'menu_order, post_title'));
else $children = wp_list_pages(array(
    'depth' => 1, 
    'show_date' => '',
    'date_format' => '',
    'child_of' => $post->ID, 
    'exclude' => '',
    'title_li' => '',
    'echo' => 0,
    'authors' => '',
    'sort_column' => 'menu_order, post_title'));
if ($children) { ?>
<ul><?php echo $children; ?>
<?php if (is_page('about') || $post->post_parent==274) { ?>
<li><a href="http://www.guitarangel.net/tcgs/" title="My TCG trading post!">Trading Post</a></li><?php } ?></ul><?php } ?>

With those extra few lines, I am telling Wordpress to show the link to my trading post only if the page is "About" or a child page of "About". The number 274 is the ID number of my "About" page and is required for WP to print it out on the correct subpages.

You can also duplicate the bold text above as many times as you like (within the UL tags) to add more links to additional pages. Just change the page slugs and ID numbers to reflect which parent page you want the link to show up on.

Please remember to keep <?php ?> wrapped around the opening and closing of each function.

Final Notes

I hope this helps anyone who wants to add a bit more usability to their WP blog! :D If you have trouble, please feel free to post your code in a comment and I will try to help you!

This article is part of my Dynamic Walkthroughs series for tweaking Wordpress.

Comments

Would you like to add one?

Michelle Feb 20, 2008

Awesome, Melissa! Thanks for writing out the tutorial… Whenever I have inspiration again I’m sure I’ll make use of it. Looking forward to future articles!

Cristina Feb 21, 2008

Yay! I’m in the process of revamping my site. I’ve already been writing up what I want showing up in each sidebar. *dances*

Jem Feb 21, 2008

I’m glad you posted this. People keep asking me how to do this in WP and I didn’t want to have to install another local copy just to figure it out :p

Hayley Feb 21, 2008

I really need to get the hang of templating, and I’m looking forward to the different sidebar on different pages tutorial!

Sofia Feb 21, 2008

Great tutorial!
But should the tag really be there?
I am looking forward to your next article!

Melissa Feb 21, 2008

Thanks all. :D

But should the tag really be there?

What tag do you mean?

Sofia Feb 21, 2008

The div one. With it my site acted up and without it it worked great.

Melissa Feb 21, 2008

Oooh! Thanks for pointing that out, Sofia! I thought I had deleted the stuff from my own sidebar page when I copied it over. :D I’ll fix it now!

Marieke Feb 21, 2008

Ohw, this is awesome ^^. Thanks for all the articles and help *smiles*

Hev Feb 21, 2008

Thanks so very much, Melissa. I can’t wait to implement this into Amarantine. This will remove a page of navigation. Yay! Less coding for me. Thanks so much. Can’t wait for the next one.

Melissa Feb 22, 2008

You’re welcome, ladies! :)

tpetek Feb 22, 2008

Thanks for the post. I, too, am providing dynamic navigation. Yours is easier to implement as I am displaying both sub-pages as well as parent pages.

I have a problem now that you might be able to help with. I have a single line to display links across the header, but one of my levels has too many pages. While I will dynamically show all 35 sub-page links down the left sidebar, the header bar of my content area is obviously too narrow. Any idea how to display some subset of the $children array that wp_list_pages produces? If I could, I might be able to enable the viewer to horizontally scroll through them. Maybe I bit off more than I can chew….?

Melissa Feb 22, 2008

No problem, Tpetek. :)

Any idea how to display some subset of the $children array that wp_list_pages produces?

So you’re wanting to separate the child page links into additional groups, is that correct? If so, you can try adding the meta_key and/or meta_value parameters in the $children declaration like this:

$children = wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0&sort_column=menu_order&meta_key=KEY");
OR
$children = wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0&sort_column=menu_order&meta_value=VALUE");

This tells the function to only list page links that have that specific custom field key or value.

Keep in mind that this will require you to go through your subpages and add a custom field entry to each page. For example, on my website I could add a key of “parent” with a value of “about” to certain pages in my about section that I wanted to list.

I’m actually glad you asked that question because I had wanted to research this method as well. I haven’t tested it yet, but if you do before I get around to it, let me know if it works ok! :D

Noellium Feb 22, 2008

Nice. :D I’ll be sure to keep this in mind. Thanks for posting it.

barbilee Feb 24, 2008

i just swiched over to wordpress and love it i mite try this out i am still laring alot of it :P

Vira Feb 26, 2008

Hi Melissa,
Nice to meet you! I’m just hopping back into the bloging scene, so my website isn’t much right now. But your writing is interesting and informative! Thanks for this wonderful tip! I’ve just started to learn wordpress, so I’ll be sure to see if I can incorporate this into my first design!

Thanks so much!
<3 Vira

Melissa Apr 04, 2008

In your dynamic sidebar/subnavigation articles there is one thing I didn’t read (or I must’ve missed it, sorry!) and that’s how you add the title of the parent page to the sidebar even when you’re browsing a subpage of that section? (like on this page it says “About navigation” with the list of subpages below it). Could you explain how you did that?

That’s a good question! I hadn’t written about that. So I will here. :)

Before this part of the code is called:

<ul><?php echo $children; ?>

You add conditional tags like in the second part of this walkthrough. For my about page, this is close to how I make it say “About Navigation” or “Gaming Navigation”:

<?php if ((is_page(’about’)) or (is_page(’about’) || $post->post_parent==274)) { ?>

<a href="/about/">About</a>

<?php } ?>

<?php elseif ((is_page(’gaming’)) or (is_page(’gaming’) || $post->post_parent==391)) { ?>

<a href="/gaming/">Gaming</a>

<?php } ?> Navigation

<ul><?php echo $children; ?>

The numbers 274 and 391 are the post/page IDs of the About and Gaming pages. They need to be the parent page’s ID in order to work.

Let me know if you need more clarification! Don’t forget to close the { brackets } and ( parentheses ) of each conditional tag or function!

Amber May 20, 2008

Hi! ^_^ First time poster/responder person here! I love your tutorial and it’s helped me out a lot. :-) But, I was wondering if there was a way you might be able to expand on this. See, I’m making a site using Wordpress as my CMS. I’m not sure how to explain this without an example, so let’s say I have a site on panda bears (they’re cute, why not?). I would have the hierarchy set up like this:

Information (top level)
-Habitat
– Zoos
- Reproduction
- Diet
– Bamboo

Multimedia (top level)
- Pictures
- Videos
(Multimedia is only part of the example to illustrate that I don’t want Information’s subpages to be displayed in Multimedia’s sidebar and vice versa)

A bit of a drawn out example, I guess; it’s a pretty complicated hierarchy. Your example allows for all of the Information section’s links to show on the “Information” section itself, but on the “Zoos” page the other subpages would not appear, not even “Habitat,” its page parent.

Would there be a way to display all the links in the information section on all its subpages, even children’s children? Sorry if I’m confusing at all, or if I’ve overlooked a section of your tutorial that would allude to this example. I’m relatively new to Wordpress, so it’s a little hard to understand for me. Thanks a lot for your time! :D

Melissa May 21, 2008

Hurrah! :cheer: Thanks for posting, Amber! I’m glad the tutorial has helped you, that is always my main goal when writing these. :) I will email you my response to this in case you haven’t come back to look.

This is actually answered in the “Subpages of Subpages” section above and has to do with the “depth” value in the code. All you’ll need to do to get all the subpages of every page to display in your sidebar is change the depth value to “0″ instead of “1″. :) I’m pretty sure this was what you were looking for but please call me out if I misunderstood.

Also, even though that is a simple solution, please don’t feel silly if you did overlook the explanation. I do that all the time myself! Wordpress is also a challenge to muddle through once you go deeper into all the unique tags.

I appreciate detailed questions like yours a lot, it helps everyone in the end in my opinion! So clear I was able to immediately think of the answer. :) I hope it helped you! Please let me know if you have any more questions. :D

Amber May 21, 2008

Thank you Melissa, that worked well! ^_^ Setting it to “0″ did almost everything I wanted it to! The only thing is that on the children’s children (like what “Bamboo” would be in my example), not all the pages show, just the ones on the same level as that page (so if there was another page on something else panda bears eat, that would be linked in the sidebar instead of the entire information section’s navigation, but nothing else). The parent pages and the original child pages themselves display great, though!

Maybe Wordpress just hates me. XD Thanks again for taking the time to answer my question! :)

Melissa May 22, 2008

I think I see what you’re trying to do now! You actually don’t need my tutorial at all for this, because it was mainly for getting only specific navigation to show within certain sections of your site. Like on my “Extras” section I only wanted the subpages for “Extras” to show and not everything else.

If you would like ALL the navigation to show, you simply just need to add the default template tag instead of what I have here in my tutorial. Or, if you’re already using it, you can change this:

‘child_of’ => $post->post_parent,

To this:

‘child_of’ => 0,

This should, according to that page I linked, display all pages no matter what parent or child page its on. I hope that helped you! :)

Amber May 23, 2008

Oh man, I keep bothering you here. I’m so sorry! :x It’s my fault, I don’t think I’m being really clear on what I mean:

You actually don’t need my tutorial at all for this, because it was mainly for getting only specific navigation to show within certain sections of your site. Like on my “Extras” section I only wanted the subpages for “Extras” to show and not everything else.

That’s what I’m trying to do. ^_^ But, what if your Extras page was the page parent for “Tutorials” (actually, I think it is!), “Tutorials” was the page parent of the three tutorials offered, and you wanted to list the tutorials in the navigation along with everything else within that particular section (Downloads, Games, Articles, etcetera)? Additionally, all the downloads, articles and games would be listed underneath their parents in the sidebar (as long as they are children of the secondary parents). That’s what I mean, I want all the subpages within a certain section to be listed in the sidebar on all pages within that section. Your tutorial almost does that, except for on the subpages of the subpages, the third level of the hierarchy. For some reason only pages of the same level appear on those particular page’s sidebars, but on the two parents above them, everything works wonderfully.

I’m probably being really annoying, so I’m going to stop harassing you with this strange, mind boggling question of mine now. (Me: :B) I hope I haven’t bothered you too much, and I’m grateful for the time you took to examine my question! ^_^

Mooty May 27, 2008

THANKYOU my friend. I needed this for a new site and was worried about it being impossible/hard to configure. But all I needed to do was copy and paste your code, I appreciate the help.

Cheers
Michael

Post a Comment

Your response may be added to a moderation queue if you have never commented before or your comment contains more than one link. If it has not appeared after a day, please contact me so I can check if it was marked as spam. Thank you! :)

Please quote people and converted code with <blockquote>. Allowed formatting includes: <strong>, <em>, <strike>, and <abbr>. You may use links that are friendly ones. :)

XD :nod: >_> :( ^_^ :P :X :goodie: :wah: :D :/ :dance: O_o 8| :| -_-; :no: XO X( :) :O :$ :cheer: :B ^^; :ohyeah: X_X ;) :T :heart: