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
Archive for February 2008
« Previous Entries | Next Entries »

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.

End of main content.