WordPress hack: Force wp_list_pages() to print current_page_item class

The wp_list_pages() function displays a list of WordPress pages as links and is often used to display navigation menus. When it prints the list of links, it adds a CSS class current_page_item to the list item tag of the current page. This allows custom styling to be applied to the link e.g. to highlight a link to indicate the page that the visitor is on.

The limitation with this is that it only works if you are viewing a page or an attachment, or are on the posts page (as set in Settings > Reading).

I was working on an archive page for a custom taxonomy and wanted to have the current_page_item CSS class added to the list item of a particular link of my choice. After poking around a bit in the wp_list_pages() code listing, I discovered it’s possible to hack the $wp_query object to make wp_list_pages() do what I wanted it to.

Here’s how:

// Get the ID of the link you want highlighted. Either:
// - hardcode it (as below)
// - or query the database to get it
$the_id = "1";


// Make a copy of the $wp_query object
$temp_query = clone $wp_query;

// Trick WordPress into thinking we're on a page with ID $the_id
$wp_query->is_page = 1;
$wp_query->queried_object_id = $the_id;

// Display pages
wp_list_pages("title_li=");

// Reset $wp_query
$wp_query = clone $temp_query;

Notes:

  • $wp_query->is_page needs to be set to 1 (true) because wp_list_pages() does not set a current page unless is_page() or is_attachment() or $wp_query->is_posts_page returns true.
  • If you only want this code to run when you are on certain page you can wrap it in an if statement that checks a WordPress conditional tag. In my case I only wanted to run this code when a taxonomy archive was being displayed so I used is_tax().
  • See http://www.jenst.se/2008/03/17/wordpress-get-id-by-post-or-page-name/ on how to query the database by post/page name to get an ID.

19 comments

  1. Matt Stein says:

    Oh how awesome — thanks for posting this! Now for the beer I owe you: what’s your PayPal donation address?

  2. Coliq says:

    Your idea is brilliant, but i don’t know why i can’t implement it.
    but i found another way with simple code.

    just call wp_list_pages() before call query or else
    best case is after get_header();

    Thanks!

  3. Sam says:

    Attention:
    The $post object is not set to the $the_id automatically using $wp_query->queried_object_id = $the_id (Even not if you reset $wp_query using new WP_Query( ‘page_id=’.$the_id).
    Use
    $post = get_post($the_id);
    to set it and wp_reset_postdata() to reset it.
    This is needed if you use e.g. count($post->ancestors) to construct your menu.

    Thank you for pointing me in the right direction!

Leave a Reply

Your email address will not be published. Required fields are marked *