Jump to Sidebar Content | Jump to Main Page Content

Begin site navigation:
End site navigation.
Begin left menu:
Topics

Pages

 
Search
 
Links
 
Subscribe
 
End of left menu.
Begin main content:
Blog

WordPress’ current_page_item Selector Got You Down?

Thursday, February 7, 2008 5:36 pm

WP 2.6.x users, keep reading and see comments!!

On my last project, I came across an interesting bug in WordPress and thought an in-depth look into troubleshooting the problem might help others who encounter it….and maybe lead to it getting fixed once and for all.

The issue arises when using WordPress as a CMS in conjunction with navigation highlighting for menus. The problem is that WordPress doesn’t pass the current_page_item selector properly on the posts page, or to its associated category pages. There’s an easy fix which I have outlined below.

Let’s say you have a Web site with a static front page called ‘Home’ and a posts page called ‘Blog.’ You have created and assigned the appropriate custom templates for these pages, and you selected them in Options > Reading in WordPress’ administrative panel:

screen image

On this site, you also have a navigation bar in header.php that calls some variety of the wp_list_pages template tag. For example:


<div id="navlinks">
<ul>
<?php wp_list_pages('title_li='); ?>
</ul>
</div>

As stated in the wp_list_pages() codex, by default, WordPress generates a list of pages that are marked with the page_item class. When displaying a page, the list item for that page is given the additional current_page_item class. So, in this example, you have also assigned attributes to these CSS properties in style.css to distinguish the current_page_item when it is active:


#navlnks .page_item a:link, #navlnks .page_item a:visited, #navlnks .page_item a:active {
color: #FFFFFF;
}


#navlnks .current_page_item a:link, #navlnks .current_page_item a:visited, #navlnks .current_page_item a:active {
color: #000000;
}

This creates a default white link that changes to black when the current page is selected:

screen image

Let’s say you also have some pages with sub-navigation, or child pages. Here, again, you’re using the default current_page_item class for a different set of pages within a menu output by wp_list_pages(), for example:


<?php
if($post->post_parent)
$children = wp_list_pages("title_li=&child_of=".$post->post_parent."&echo=0"); else
$children = wp_list_pages("title_li=&child_of=".$post->ID."&echo=0");
if ($children) { ?>
<div id="sidebar">
<ul>
<?php echo $children; ?>
</ul>
</div>
<?php } ?>

For these child pages, you’ve also styled WordPress’ default current_page_parent selector to identify the associated current page in the top-level navigation. For example:


#navlnks .current_page_parent a:link, #navlnks .current_page_parent a:visited, #navlnks .current_page_parent a:active {
color: #000000;
}

When you’re on a page and you click into a child page, the top-level page indicator should remain so that you know you’re still within that same section of the Web site. For example:

screen image

This works just fine for pages, but not for pages with posts. On posts pages, the top-level active page indicator disappears:

screen image

In fact, for pages with posts, WordPress doesn’t pass the current_page_item class in the HTML at all:


<div id="navlnks">
<ul>
<li class="page_item page-item-1"><a href="http://www.umaitech.com" title="Home">Home</a></li>
<li class="page_item page-item-2"><a href="http://www.umaitech.com /about/" title="About">About</a></li>
<li class="page_item page-item-3"><a href="http://www.umaitech.com /portfolio/" title="Portfolio">Portfolio</a></li>
<li class="page_item page-item-4"><a href="http://www.umaitech.com /news/" title="News">News</a></li>
<li class="page_item page-item-5"><a href="http://www.umaitech.com /blog/" title="Blog">Blog</a></li>
</ul>
</div>

Interestingly, if you go back to Options > Reading and don’t select a posts page, it works. To replicate this, just leave the default – Select – option for the Posts page as shown here:

screen image

After doing this, WordPress properly outputs the current_page_item class in the HTML:


<div id="navlnks">
<ul>
<li class="page_item page-item-1"><a href="http://www.umaitech.com" title="Home">Home</a></li>
<li class="page_item page-item-2"><a href="http://www.umaitech.com /about/" title="About">About</a></li>
<li class="page_item page-item-3"><a href="http://www.umaitech.com /portfolio/" title="Portfolio">Portfolio</a></li>
<li class="page_item page-item-4"><a href="http://www.umaitech.com /news/" title="News">News</a></li>
<li class="page_item page-item-5 current_page_item"><a href="http://www.umaitech.com/blog/" title="Blog">Blog</a></li>
</ul>

At first I thought this would suffice as a workaround – it brings back the top-level selector:

screen image

But a big problem remains. When you click on an individual post or navigate into category pages, the current-cat class is properly identified, but the top-level selector disappears:

screen image

Therefore, it isn’t much of a workaround after all. After hours of head scratching and searching through the WordPress forums, I stumbled upon an unresolved discussion thread about this very same problem that was initiated 11 months ago. This directly led me to a solution – specifically, by using code posted by munzli.

If you’re experiencing this same problem and want to adapt the code, here’s what you need to do. This assumes you’re running WordPress version 2.3.2 or later and that you have properly selected your template pages in the Options > Reading panel as I discussed in the first example above:

1. Edit the wp-includes/classes.php file
2. ADD the following code as lines 520 and 521 (WP 2.5 users, add it as lines 563 and 564. WP 2.5.1 users, add it as lines 558 and 559. WP 2.6.x users, add it as lines 577 and 578):


elseif ($page->ID == $current_page || ($current_page == 0 && $page->ID == get_settings('page_for_posts')))
$css_class .= ' current_page_parent';

3. Save

The final result:

screen image

This solution ensures that the current_page_item selector is retained on top-level navigation for child pages, category pages, and single post pages — on both “regular” WordPress pages and “posts” pages. Until it’s incorporated as an actual bug fix, however, remember to re-add it anytime you upgrade WordPress.

Happy coding!

Comments are closed.

Comments

  1. Any idea on where this would go in the file for wp 2.7?

    It’s astonishing to me that through all these version modifications, there hasn’t been someone checking into this. Have you considered reporting this bug to WP?

    Thanks for the awesome insight. I truly appreciate it!

  2. Hi Betsy,

    Thanks very much, worked like a dream :-) I’m using WP 2.6.2 so added the code as described but not looking to upgrade just yet as finally have the site set up as needed and don’t need the new version just yet!

    I’m using WP as a CMS and have one problem still. While relevant section (‘Blog’) is now highlighted for posts, the URL has not changed nor my breadcrumb trail (I’m using the plug-in Yoast Breadcrumbs).

    So instead of http://www.domainname.co.uk/blog/2008/12/ I get http://www.domainname.co.uk/2008/12/ or instead of http://www.domainname.co.uk/blog/category/sport/ I get http://www.domainname.co.uk/category/sport/

    My permalinks are set-up as /%category%/%postname%/
    which works fine for all pages but do I need to change for the posts to work to?

    Great post, thanks for the advice :-)

    Regards,

    Adrian

  3. Hi Erika,

    The good news is that the bug fix has been rolled into WP 2.7! It took awhile, but this problem is now resolved. Yeah, I’m even there in the official props list. Woo-hoo!

    So, if you upgrade to WP 2.7, you no longer need to edit the classes.php file and this post is entirely irrelevant to you. But if you are waiting awhile to upgrade, the info here is still useful to you until you do upgrade.

  4. Hi, Betsy;

    I just upgraded to 2.7 but…
    – I’ve set Settings > Reading to “Latest News” but the URL is missing a backslash which results in an invalid URL
    – when I use in header.php, the category-specific tab is still not highlighted

    Is there a working solution in 2.7 that I can find somewhere?

  5. Okay, so code tag doesn’t work. Let’s try this in plain text.
    <ul class=”tabs”>
    <?php wp_list_pages(‘title_li=’); ?>
    </ul>

  6. Betsy, I found some hope in your solution here…and was happy to see this fixed in 2.7. However, for me it isn’t fixed, and it may be a wp theme issue. the theme I’m using lists parents only in the header bar. I’ve got 5 subpages under a parent page, and when I’m on a subpage, the parent page is not highlighted.

    I’m running the latest wp 2.7. Any ideas on where I could start to fix this?

    Thanks,

    Sam

  7. Hey everyone. It looks like there are lot of people having trouble getting this to work in WP 2.7. This was a WP bug since inception, so it never worked properly before version 2.7. Therefore, many themes (including the default WP theme) are missing the .current_page_parent class.

    If you have access to your theme’s stylesheet — usually the default style.css — you can add it yourself. If you’re a WP user, go to Appearance > Editor and click on Stylesheet (style.css). Feel free to use these sample class definitions as a starting point:

    #navlnks .current_page_parent a:link, #navlnks .current_page_parent a:visited, #navlnks .current_page_parent a:active {
    color: #000000;
    }

    Happy New Year!

  8. Hi,

    I am using wordpress 2.7 and i have the same issue that selecting post pages of parent page, the parent link is no more highlighted. Can you please on which line of classes.php I should alter to solve this problem.

    Your help will be greatly appreciated.

    Thanks
    ishafaat
    http://tinyurl.com/8xrdwo

  9. Hi Betsy,

    After wading through all of the above, it’s clear this issue is emphatically *not* resolved for wp 2.7. To be fair to wordpress, this is probably a theme issue, as menu generation is frequently taken over by the theme.

    Here’s my example. I use only a single (left) navigaion menu, with nesting of pages. All my menu items are pages, except for “News”, which is a post. “News” is nested under “News and events”. If you click your way to “News”, the menu closes up, displaying only the parent (“News and events”) and hiding the menu item for the page you are looking at (“News”).

    The solution undoubtedly involves a multi-way interaction between classes.php, my theme (atahualpa3) and multiple style sheets. That is, it is diabolical. I’ll post the solution when I find one…

  10. Nice one, it worked. Was searching for some time for this one.

  11. Hi Betsy

    Any idea on where in the classes.php the lines must be inserted.

    Best
    Jan


End of main content.