I'm using the wp_list_categories() function which generates an unordered list with list items and anchor tags for the categories. Is there any way to add HTML attributes to the <a> tags which hold the category links?

I'd like to add a title attribute which is the same as the category, and a class attribute, but looking at the docs, in the list of associative array properties I can't see how to do this?

The code I'm using is:

    echo '<ul class="cat-sidebar-list">';
        $args_list = array(
        'taxonomy' => 'news_categories',
        'show_count' => false,
        'hierarchical' => true,
        'hide_empty' => false,
        'title_li' => '',
        echo wp_list_categories($args_list);
    echo '</ul>';

Thanks in advance for any help.

  • wp_list_categories() doesn't have an option to modify attributes for category link. Code screenshot: monosnap.com/file/zGKB1D9HxeavjtALrg56MQdvKTulkC You can either use the filter wp_list_categories to modify the output using regex, or you can write a custom function.
    – Kumar
    Sep 8, 2020 at 3:22

3 Answers 3


The default walker used by wp_list_categories() (Walker_Category) has a hook (a filter hook) named category_list_link_attributes which you can use to add custom title and class (as well as other attributes like data-xxx) to the anchor/a tag (<a>) in the HTML list generated via wp_list_categories().

So for example, you can do something like:

add_filter( 'category_list_link_attributes', 'my_category_list_link_attributes', 10, 2 );
function my_category_list_link_attributes( $atts, $category ) {
    // Set the title to the category description if it's available. Else, use the name.
    $atts['title'] = $category->description ? $category->description : $category->name;

    // Set a custom class.
    $atts['class'] = 'custom-class category-' . $category->slug;
//  $atts['class'] .= ' custom-class';                 // or append a new class
//  $atts['class'] = 'custom-class ' . $atts['class']; // or maybe prepend it

    return $atts;
  • 1
    Thanks ever so much Sally!
    – pjk_ok
    Sep 14, 2020 at 18:27

Custom Walker

The function wp_list_categories accepts a (custom) walker. That gives you the possibility to add a custom function that adds class and title attribute to the output. The function has no filter hook so that you have not the option to change the default output of the function.

an example to use a custom walker at the function.

$args = array(
    'orderby' => 'id',
    'show_count' => 0,
    'walker' => new My_Custom_Walker_Category(),

The custom walker is an extension of the default, like (Documentation)

class My_Custom_Walker_Category extends Walker_Category {
    function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) {

Only CSS classes

A simple solution is possible only for the CSS classes. The default walker has a filter hook to change, enhance the CSS classes - category_css_class. The filter has all parameters documented.

         * Filters the list of CSS classes to include with each category in the list.
         * @since 4.2.0
         * @see wp_list_categories()
         * @param array  $css_classes An array of CSS classes to be applied to each list item.
         * @param object $category    Category data object.
         * @param int    $depth       Depth of page, used for padding.
         * @param array  $args        An array of wp_list_categories() arguments.
        $css_classes = implode( ' ', apply_filters( 'category_css_class', $css_classes, $category, $depth, $args ) );

The Walker

More hooks and hints about the Walker class will you find inside the documentation. The Walker has three hooks.

  • category_description
  • category_css_class
  • category_list_link_attributes

If you only wanted to output the category name as the title attribute, you could do that simply by entering the category name in the Category Description field because the default output is to use that field as the title attribute UNLESS you set that flag in $args to 0 (false - see use_desc_for_title the default is 1, true).

But a simpler way to do what you want is to output the results of wp_list_categories() instead of echoing (set 'echo' to 0 instead of the default 1) and then you can set your HTML however you like for $output.

So an example (similar to that found in the Codex) would be (remember you can remove/ignore any for which the default is what you want):

wp_list_categories( $args = '' ) {
$defaults = array(
    'child_of'            => 0,
    'current_category'    => 0,
    'depth'               => 0,
    'echo'                => 0,
    'exclude'             => '',
    'exclude_tree'        => '',
    'feed'                => '',
    'feed_image'          => '',
    'feed_type'           => '',
    'hide_empty'          => 1,
    'hide_title_if_empty' => false,
    'hierarchical'        => true,
    'order'               => 'ASC',
    'orderby'             => 'name',
    'separator'           => '<br />',
    'show_count'          => 0,
    'show_option_all'     => '',
    'show_option_none'    => __( 'No categories' ),
    'style'               => 'list',
    'taxonomy'            => 'category',
    'title_li'            => __( 'Categories' ),
    'use_desc_for_title'  => 1,

$parsed_args = wp_parse_args( $args, $defaults );

$categories = get_categories( $parsed_args );
 if ( ! empty( $categories ) ) {
 echo '<ul>';
   foreach ($categories as $category) {
   echo '<li class="' . esc_attr( $parsed_args['class'] ) . '">' . $parsed_args['title_li'];

   echo '</ul>';

Keep in mind that while you can add any additional style classes you want this way, the default is to output a class for each category ID, so you already have some granular style options built in. And as mentioned the default output for the title attribute is the Category Description so assuming you're not already using that field for an actual description, just putting the Category name there will do what you want without additional code.

EDITED: Chewy, you can remove any lines in the $args (defaults) that are set as you already want them to be according to their defaults - you only need to list them if you are changing from what is the default per the Codex. In the list above, 'echo' is set to 0 meaning that it will return the results to you, not list them, which is why just below that in the foreach statement you have to open the UL, then loop through the results to create the LI for each one.

THE ONLY reason I can see to do this is so you can add the styles you said in your OP that you want to add.....if you can live with the unique styles WP adds already (the category ID is added as a class to each category listed), then you don't need to do any of this, all you need to do is call wp_list_categories() in your template where you want them, and put your preferred Title Attribute in the category's Description field.

  • Hi @Trisha that code is throwing an error - I think it's an error in the foreach part of it, but I can't seem to see where.
    – pjk_ok
    Sep 9, 2020 at 0:21
  • My apologies Chewy, I just threw that together as an example, I didn't take the time to test it. What error do you get?
    – Trisha
    Sep 9, 2020 at 1:30
  • The syntax highlighter is highlighting the first line of the foreach method and is showing the following message is the VSCode debugger "message": "syntax error, unexpected '$categories' (T_VARIABLE), expecting '('",
    – pjk_ok
    Sep 9, 2020 at 2:27
  • Gah! My bad.... that line should be written with the parenthesis, like this: foreach ( $categories as $category ) {
    – Trisha
    Sep 9, 2020 at 14:56
  • It's now showing more errors on the line inside the foreach. Also is this code meant to go in my functions.php file or template file (where my current code is)? I get more errors showing in the template file than when in functions.php but all the errors show on the line inside the foreach function. Sample image for errors when in functions.php snipboard.io/qXFD17.jpg
    – pjk_ok
    Sep 9, 2020 at 21:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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