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?

Feb 20, 2008 @ 10:10pm

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!

Feb 21, 2008 @ 12:12am

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*

Feb 21, 2008 @ 3:03am

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

Feb 21, 2008 @ 4:04am

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

Feb 21, 2008 @ 12:12pm

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

Feb 21, 2008 @ 12:12pm

Thanks all. :D

But should the tag really be there?

What tag do you mean?

Sofia
Feb 21, 2008 @ 12:12pm

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

Feb 21, 2008 @ 12:12pm

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!

Feb 21, 2008 @ 1:01pm

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

Feb 21, 2008 @ 4:04pm

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.

Feb 22, 2008 @ 10:10am

You’re welcome, ladies! :)

tpetek
Feb 22, 2008 @ 11:11am

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….?

Feb 22, 2008 @ 12:12pm

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

Feb 22, 2008 @ 3:03pm

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

Feb 24, 2008 @ 12:12am

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

Feb 26, 2008 @ 11:11am

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

Apr 04, 2008 @ 6:06pm

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!

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. :)

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