WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

The below code is for listing the custom post types itself and its children in the sidebar. The code works great but does not highlight the sub pages.

In functions.php:

* Gets the id of the topmost ancestor of the current page. Returns the current
* page's id if there is no parent.
* @uses object $post
* @return int 
function get_post_top_ancestor_id(){
global $post;

    $ancestors = array_reverse(get_post_ancestors($post->ID));
    return $ancestors[0];

return $post->ID;

and adding this code to the sidebar:

#echo $getid;
global $post;
if (is_single($post->ID)) {$pg_li .="current_page_item";}
else {
$pg_li .="page_item";}
<h3><?php the_title();?></h3>
<li class="<?php echo $pg_li; ?>">
<a href="<?php the_permalink(); ?>">BIOGRAPHY</a>
<li class="<?php echo $pg_li; ?>">
'child_of'=>$getid ,
'hierarchical' => 1,
wp_list_pages( $args );

I am not familiar with PHP, and a friend helped me to write this code. So what am I missing to highlight the current sub menu of that custom post type?

share|improve this question
Do you actually have a unique style in your css for .current_page_item? – Johannes Pille Nov 27 '12 at 9:00
@JohannesPille yes, i have.. – sez Nov 28 '12 at 18:25
Would it be possible to list them with a custom navigation menu instead of the code you used? Reason I ask is because if you can replace it with a custom navigation menu you can use: vayu.dk/… – Piet Jan 24 '13 at 13:13
Can we see the rendered page? – Alex Thomas May 16 '13 at 14:41
There is a hack on the link: mark-leong.com/…, Or checkout this one kucrut.org/wp_list_pages-for-custom-post-types – sven Apr 1 '14 at 8:14

The problem with this code is that the query is being altered and current_page_item is being lost. This is the part causing problems.

$post = get_post( $getid );
setup_postdata( $post );

If you comment out those two lines you'll see that current_page_item appears.

There are also some secondary problems with this code that have no bearing on the main problem.

  1. <p></p> should not exist as a child element of <ul>. Only <li> is allowed.
  2. <h3>...</h3> also should not exist as a child element of <ul> for the same reasons as #1.
  3. The if statement setting the CSS class for the "Biography" link will return true on any single page, not just the parent page.
  4. wp_list_pages() outputs a list of <li>...</li> tag pairs so it doesn't need to be wrapped with another pair of <li>...</li> tags.

The following code corrects all the issues.

$getid = get_post_top_ancestor_id(); 
global $post;
<h3><?php echo get_the_title( $getid );?></h3>
    if ( $post->ID == $getid ) {
        $pg_li .= "current_page_item";
    } else {
        $pg_li .= "page_item";
    <li class="<?php echo $pg_li; ?>">
        <a href="<?php echo get_permalink( $getid ); ?>">BIOGRAPHY</a>
        'post_type' => 'artists',
        'child_of' => $getid,
        'sort_column' => 'menu_order',
        'hierarchical' => 1,
        'title_li' => __('')
    wp_list_pages( $args );
share|improve this answer

There is a fix coming up for the same, here is the ticket: https://core.trac.wordpress.org/changeset/27755

In case you need it urgently, you can give this a try

Original Answer by @goldenapples, here is the link:

Dynamic navigation for custom post type (pages)

function wp_list_post_types( $args ) {
$defaults = array(
    'numberposts'  => -1,
    'offset'       => 0,
    'orderby'      => 'menu_order, post_title',
    'order'      => 'ASC',
    'post_type'    => 'page',
    'depth'        => 0,
    'show_date'    => '',
    'date_format'  => get_option('date_format'),
    'child_of'     => 0,
    'exclude'      => '',
        'include'      => '',
    'title_li'     => __('Pages'),
    'echo'         => 1,
    'link_before'  => '',
    'link_after'   => '',
    'exclude_tree' => '' );

$r = wp_parse_args( $args, $defaults );
extract( $r, EXTR_SKIP );

$output = '';
$current_page = 0;

// sanitize, mostly to keep spaces out
$r['exclude'] = preg_replace('/[^0-9,]/', '', $r['exclude']);

// Allow plugins to filter an array of excluded pages (but don't put a nullstring into the array)
$exclude_array = ( $r['exclude'] ) ? explode(',', $r['exclude']) : array();
$r['exclude'] = implode( ',', apply_filters('wp_list_post_types_excludes', $exclude_array) );

// Query pages.
$r['hierarchical'] = 0;
$pages = get_posts($r);

if ( !empty($pages) ) {
    if ( $r['title_li'] )
        $output .= '<li class="pagenav">' . $r['title_li'] . '<ul>';

    global $wp_query;
    if ( ($r['post_type'] == get_query_var('post_type')) || is_attachment() )
        $current_page = $wp_query->get_queried_object_id();
    $output .= walk_page_tree($pages, $r['depth'], $current_page, $r);

    if ( $r['title_li'] )
        $output .= '</ul></li>';

$output = apply_filters('wp_list_pages', $output, $r);

if ( $r['echo'] )
    echo $output;
    return $output;
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.