scriptygoddess

10 Feb, 2009

Show subnavigation for just the main nav/section you're in (WordPress)

Posted by: Jennifer In: WordPress|WordPress Hacks

When you use wp_list_pages() – you get a full dump of everything. If you restrict the depth, then you might not be showing the child / subpages under each page.

The code I have below will first list only the "main nav" (parent) pages. If you click on one of the main nav / (parent) pages and it has children pages – then it will list ALL subpages under that parent page (including if there are multiple parent/child pages under it – it will list all of them). So for example…

If this is your page structure:

  • Home
  • About Us
    • Who we are
    • What we do
    • Why you want to hire us
      • Our prices
      • Our people
      • Our philosopy
  • Contact Us
    • Map to our offices
    • Phone Numbers
    • Contact Form

So this would first list just the main nav items – Home, About Us, and Contact us. Like this:

  • MAIN NAV (you can change/remove this – just put it here for explanatory purposes)
    • Home
    • About Us
    • Contact Us

Once you click on About us – all the subnav under about us is revealed in a separate list below the main nav items – and will stick around for as long as you're in an "about us" page. Kind of like this:

  • MAIN NAV (you can change/remove this – just put it here for explanatory purposes)
    • Home
    • About Us
    • Contact Us
  • SUB NAV FOR: About Us
    • Who we are
    • What we do
    • Why you want to hire us
      • Our prices
      • Our people
      • Our philosopy

<ul>
<?php wp_list_pages('title_li=<h2>MAIN NAV</h2>&depth=1' ); ?>
</ul>
<?php
if ($post->post_parent == 0) {
$children = wp_list_pages("title_li=&child_of=".$post->ID."&echo=0");
$parentpage = $wpdb->get_row("SELECT ID, post_title, post_name FROM $wpdb->posts WHERE ID = '".$post->ID."'");
}
if ($post->post_parent != 0) {
$next_post_parent = $post->post_parent;
while ($next_post_parent != 0) {
$children = wp_list_pages("title_li=&child_of=".$next_post_parent."&echo=0");
$parentpage = $wpdb->get_row("SELECT ID, post_title, post_parent, post_name FROM $wpdb->posts WHERE ID = '".$next_post_parent."'");
$next_post_parent = $parentpage->post_parent;
}
}
?>
<?php if ($children) { ?>
<ul>
<li><h2>SUBNAV FOR: <a href="<?php echo get_permalink($parentpage->ID); ?>"><?php echo $parentpage->post_title; ?></a></h2>
<ul>
<?php echo $children; ?>
</ul>
</li>
</ul>
<?php } ?>

If someone knows of an easier/better way than this – please let me know. I've looked and couldn't find anything (and was happy to have figured something out that worked!)

You can put this anywhere in your template file really. This code would be used OUTSIDE of the WordPress loop…

Update: So just a bit more advanced "features" here. On my installment of this – I wanted only the first level of subnav pages visible, and then if you clicked on a subnav page that had child pages – then that list became visible. And if one of those pages had child pages – then that 3rd level of pages would be shown also (all the while keeping all the other sub nav for this section visible. When I get more time, I'll include screenshots to demonstrate what I'm talking about. In the meantime , I'm dumping the code here before I lose it again! LOL! Oh, also – I wanted to add some kind of indicator on the subnav links that showed there was navigation below it – like an + sign or something…

<script type="text/javascript" src="/js/jquery-1.3.1.min.js"></script>
<script type="text/javascript">
jQuery.noConflict();
jQuery(document).ready( function() {
jQuery('ul').parent('li').addClass("parentul");
});
</script>

That will find any unordered list that is WITHIN a list item – and apply the class "parentul" to the PARENT li item.

Then I used the following styles to hide the blocks that needed to be hidden, and show the "+" sign next to the linkts that had more subnav items below them:

#sidebar .current_page_ancestor ul,
#sidebar .current_page_item ul,
#sidebar .current_page_ancestor.current_page_parent .current_page_item ul,
#sidebar .current_page_ancestor.current_page_parent ul {
display: block;
}
#sidebar .current_page_item ul ul,
#sidebar .current_page_ancestor.current_page_parent ul ul,
#sidebar ul ul ul {
display: none;
}
#sidebar ul li,
#sidebar ul li ul li,
#sidebar ul li ul li ul li {
padding-left: 8px;
}
#sidebar ul li.parentul {
background:url(images/more.gif) 0 3px no-repeat;
}

The "more.gif" was my + sign.

Just to clarify more… Here are the screenshots:

This is the default view of wp_list_pages:
picture-11

Here is what the code above will do:

If there is no subnav pages under the section we're in – no subnav is displayed…
picture-71

picture-41
In this view, we're in the "about" section – on the "What we do" page… notice that you're seeing only the subnav pages under "about", and the pages under "why you want to hire us" are collapsed with the + sign (my "more.gif" in front of the link…

picture-5
Now we're on the "why you want to hire us" page – so the subnav under that page are revealed.

picture-8
Now we're on a subnav of a subnav … the "our prices" page under "why you want to hire us" (in the About section)

I tweaked the stylesheets a bit for these screenshots. You'll have to play with it to suit your needs. For the screenshots, I wanted to bold the section we're in in the main nav, and the subnav page, as well as the subnav page, and subnav "parent" page… Here's the styles I used to do that:

#sidebar .current_page_ancestor ul,
#sidebar .current_page_item ul,
#sidebar .current_page_ancestor.current_page_parent .current_page_item ul,
#sidebar .current_page_ancestor.current_page_parent ul {
display: block;
}
#sidebar .current_page_item ul ul,
#sidebar .current_page_ancestor.current_page_parent ul ul,
#sidebar ul ul ul {
display: none;
}
#sidebar ul li,
#sidebar ul li ul li,
#sidebar ul li ul li ul li {
padding-left: 8px;
}
#sidebar ul li.parentul {
background: none;
}
#sidebar ul ul li.parentul {
background:url(images/more.gif) 0 3px no-repeat;
}
#sidebar .current_page_parent li,
#sidebar .current_page_item li {
font-weight: normal;
}
#sidebar li.current_page_ancestor,
#sidebar li.current_page_item {
font-weight: bold;
}

10 Responses to "Show subnavigation for just the main nav/section you're in (WordPress)"

1 | Anonymous

February 10th, 2009 at 6:41 pm

Avatar

Mom Blogs – Blogs for Moms…

2 | Josh

April 3rd, 2009 at 10:16 am

Avatar

Thanks for sharing! I've been looking for this solution for awhile now. Used to make different sidebars for each category but this is much, much better.

3 | Corinne

April 22nd, 2009 at 6:56 pm

Avatar

Thank you thank you!!

I have been looking for something like this for ages… This is perfect.

Works so well for CMS type websites built with wordpress and makes so much sense. Not sure why WP doesn't make functions like this easier.

Thanks again for sharing your work xx

4 | David Sharkey

September 15th, 2009 at 12:56 am

Avatar

This is great, but I need to make a change. I need to make the sub categories appear inline along a horizontal menu bar. I've done this however I need to put a '|' between the items as a seperator. Where would I include this is the php code?

any help would be great

thanks

5 | Virg

November 19th, 2009 at 9:15 am

Avatar

Excellent code! From experience trying many things I didn't think it would work until I saw it! You just add the code in your page template and that's it.

But how do I remove the bulletin from "main nav" and"sub nav" like you have in the pictures?

6 | Jennifer

November 19th, 2009 at 9:20 am

Avatar

@virg: Not sure if this is what you mean, but I had a css reset on the page that created those screenshots – so ul { list-style:none; } (or add more selectors to specify just the UL in your sidebar… (If you send me a link I can probably be more specific)

7 | Virg

November 19th, 2009 at 10:34 am

Avatar

Thanks for replying! I'm pretty new with WP. I don't think I'm putting the { list-style:none; } where I'm supposed to because it appears as text. Even without the bracket spaces. Here is the link you requested http://www.graphictask.com/?page_id=2

(I took off the Main Nav.)

8 | Jennifer

November 19th, 2009 at 10:39 am

Avatar

You actually want to put that in your css file.

9 | Virg

November 19th, 2009 at 6:45 pm

Avatar

Right! Sorry. Do you know if it's possible to give the code a ? I'm trying to place it on top of my content. I made a content div id for the content itself and tried float:bottom but instead the childpage links go on the bottom.

10 | Virg

November 19th, 2009 at 7:19 pm

Avatar

sorry, nvm. I fixed the problem with the content on top.

Featured Sponsors

Genesis Framework for WordPress

Advertise Here


  • Scott: Just moved changed the site URL as WP's installed in a subfolder. Cookie clearance worked for me. Thanks!
  • Stephen Lareau: Hi great blog thanks. Just thought I would add that it helps to put target = like this:1-800-555-1212 and
  • Cord Blomquist: Jennifer, you may want to check out tp2wp.com, a new service my company just launched that converts TypePad and Movable Type export files into WordPre

About


Advertisements