wp_list_categories, Add class to all list items with children

I’m using wp_list_categories(); to show a list of all the terms within a custom taxonomy but I need to style list items that have children differently to those that don’t.

Is there a way, PHP or jQuery, that I can give all parent elements a special class?

Related posts

Leave a Reply

2 comments

  1. jQuery solution:

    You could try this if you want to use jQuery:

    <script>
    jQuery(document).ready(function($) {
        $('li.cat-item:has(ul.children)').addClass('i-have-kids');
    }); 
    </script>
    

    to add the class i-have-kids to all the li parents that include the items ul.children, within the HTML generated from wp_list_categories().

    Category walker solution:

    You could take a look at the Walker_Category class in /wp-includes/category-template.php and extend it with an extra part like:

    $termchildren = get_term_children( $category->term_id, $category->taxonomy );
    if(count($termchildren)>0){
        $class .=  ' i-have-kids';
    }
    

    If we skip the feed image and feed parts, the extended walker could look like this:

    class Walker_Category_Find_Parents extends Walker_Category {
        function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {
            extract($args);
    
            $cat_name = esc_attr( $category->name );
            $cat_name = apply_filters( 'list_cats', $cat_name, $category );
            $link = '<a href="' . esc_url( get_term_link($category) ) . '" ';
            if ( $use_desc_for_title == 0 || empty($category->description) )
                $link .= 'title="' . esc_attr( sprintf(__( 'View all posts filed under %s' ), $cat_name) ) . '"';
            else
                $link .= 'title="' . esc_attr( strip_tags( apply_filters( 'category_description', $category->description, $category ) ) ) . '"';
                $link .= '>';
                $link .= $cat_name . '</a>';
    
            if ( !empty($show_count) )
                $link .= ' (' . intval($category->count) . ')';
    
                    if ( 'list' == $args['style'] ) {
                            $output .= "t<li";
                            $class = 'cat-item cat-item-' . $category->term_id;
    
                            $termchildren = get_term_children( $category->term_id, $category->taxonomy );
                            if(count($termchildren)>0){
                                $class .=  ' i-have-kids';
                            }
    
                            if ( !empty($current_category) ) {
                                    $_current_category = get_term( $current_category, $category->taxonomy );
                                    if ( $category->term_id == $current_category )
                                            $class .=  ' current-cat';
                                    elseif ( $category->term_id == $_current_category->parent )
                                            $class .=  ' current-cat-parent';
                            }
                            $output .=  ' class="' . $class . '"';
                            $output .= ">$linkn";
                    } else {
                            $output .= "t$link<br />n";
                    }
            }
        }
    

    You could further take out the parts that you don’t need.

    Usage example:

    <?php 
    $args = array(
      'taxonomy'     => 'my_custom_taxonomy_slug',
      'orderby'      => 'name',
      'hide_empty'   => 0,
      'title_li'     => '',
      'hierarchical' => 1,
      'walker'       => new Walker_Category_Find_Parents(),
    );
    ?>
    <ul class="menu">
       <?php wp_list_categories( $args ); ?>
    </ul>
    

    Output example:

    Here’s a list example, using the Walker_Category_Find_Parents walker:

    List example

    with the following HTML structure:

    <ul class="menu">
        <li class="cat-item cat-item-1">
            <a href="http://example.com/category/plants/">plants</a>
        </li>
        <li class="cat-item cat-item-2 i-have-kids">
            <a href="http://example.com/category/animals/">animals</a>
            <ul class="children">
                <li class="cat-item cat-item-3 i-have-kids">
                    <a href="http://example.com/category/animals/birds/">birds</a>
                    <ul class="children">
                        <li class="cat-item cat-item-4">
                            <a href="http://example.com/category/animals/birds/falcons/">falcons</a>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
        <li class="cat-item cat-item-5">
            <a href="http://example.com/category/stones">stones</a>
        </li>
    </ul>
    

    I just removed the title attributes to make it more readable.

    But you can see where the i-have-kids class is added to the li tags with children.

    When I visit the / Animals / Birds / category, the HTML structure becomes:

    <ul class="menu">
        <li class="cat-item cat-item-1">
            <a href="http://example.com/category/plants/">plants</a>
        </li>
        <li class="cat-item cat-item-2 i-have-kids current-cat-parent">
            <a href="http://example.com/category/animals/">animals</a>
            <ul class="children">
                <li class="cat-item cat-item-3 i-have-kids current-cat">
                    <a href="http://example.com/category/animals/birds/">birds</a>
                    <ul class="children">
                        <li class="cat-item cat-item-4">
                            <a href="http://example.com/category/animals/birds/falcons/">falcons</a>
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
        <li class="cat-item cat-item-5">
            <a href="http://example.com/category/stones">stones</a>
        </li>
    </ul>
    
  2. You can hook into the filter that is implemented for this exact purpose as follows. My example will add a “has_children” class to the parent element.

    function add_category_parent_css($css_classes, $category, $depth, $args){
        if($args['has_children']){
            $css_classes[] = 'has_children';
        }
        return $css_classes;
    }
    
    add_filter( 'category_css_class', 'add_category_parent_css', 10, 4);