Ways to give a wp_list_pages menu link specific class names?

Okay well in that case the way you’ve suggested in your question will not work as intended. It will put the same class on each <span>, that class would also be the post_name of the current page you are on.

You do have two options that you can use, one being much easier than the other:

Method One

Each <li> item generated by wp_list_pages() is given a unique class. The class follows a pattern of page-item-$ID where $ID is the ID of the page currently being processed by wp_list_pages().

If you change the link_before parameter to be just <span></span> then you can target the spans I’m your css like so .page-item-$ID span. Though I imagine this would get tedious if you had loads of pages.

Method Two

You could write a custom walker for the wp_list_pages() function and pass it into the walker parameter of the function. This would give you considerably more control over the naming of classes. Attached is a custom walker that you can use, with an explanation beneath.

Add to functions.php:

class WPSE_130877_Custom_Walker extends Walker_Page {

    function start_el( &$output, $page, $depth, $args, $current_page = 0 ) {
        if ( $depth )
            $indent = str_repeat("\t", $depth);
        else
            $indent="";
            extract($args, EXTR_SKIP);
            $css_class = array('page_item', 'page-item-'.$page->ID);
        if ( !empty($current_page) ) {
            $_current_page = get_post( $current_page );
            if ( in_array( $page->ID, $_current_page->ancestors ) )
                $css_class[] = 'current_page_ancestor';
            if ( $page->ID == $current_page )
                $css_class[] = 'current_page_item';
            elseif ( $_current_page && $page->ID == $_current_page->post_parent )
                $css_class[] = 'current_page_parent';
        }
        elseif ( $page->ID == get_option('page_for_posts') ) {
            $css_class[] = 'current_page_parent';
        }

        $css_class = implode( ' ', apply_filters( 'page_css_class', $css_class, $page, $depth, $args, $current_page ) );
        $icon_class = get_post_meta($page->ID, 'icon_class', true); //Retrieve stored icon class from post meta

        $output .= $indent . '<li class="' . $css_class . '">';
            $output .= '<a href="' . get_permalink($page->ID) . '">' . $link_before;

                if($icon_class){ //Test if $icon_class exists
                    $output .= '<span class="' . $icon_class . '"></span>'; //If it exists output a span with the $icon_class attached to it
                }

                $output .= apply_filters( 'the_title', $page->post_title, $page->ID );
            $output .= $link_after . '</a>';

        if ( !empty($show_date) ) {
            if ( 'modified' == $show_date )
                $time = $page->post_modified;
                else
                $time = $page->post_date;
                $output .= " " . mysql2date($date_format, $time);
        }
    }
}

Call your wp_list_pages() like below:

wp_list_pages(array(
    'sort_column' => 'menu_order',
    'title_li'    => '',
    'echo'        => 1,
    'walker' => new WPSE_130877_Custom_Walker()
)); 

Take note that we have removed the link_before parameter and added in a walker parameter, which takes an instance of our custom walker class. Notice it has the same name as the snippet of code i’ve asked you to put into your functions.php.

The code for the custom walker is essentially default WordPress code but we are overriding it with the new walker. We are only making a small edit in the middle of the default WordPress function that handles the markup for the beginning of each page-item. All of the code I added has comments next to it.

So as build the markup for each page-item we check to see if it has a meta key of icon_class, if it does then we add in a <span> tag with our icon_class value before the page-item link. The conditional is there to prevent printing out redundant elements, however the code could easily be edited to add a default icon in.

Essentially all you need to do is build a meta box for your pages and then replace icon_class in the above code with whatever you decide to call the key that holds the class name. It should be noted that the code expects icon_class to return a string.

Leave a Comment