I don't want to style the default widget with only CSS. I want to display the default 'Categories' widget content with my own HTML structure.

Is there available any filter or hook to do that?

  • 2
    Write your own widget that does what you want. Start by copying the code of the categories widget and do modifications. Jun 15, 2016 at 6:40
  • Thanks, I usually follow this trick to do my widget modifications. It's the easier method seems to me.
    – Eh Jewel
    Feb 26, 2018 at 12:56

3 Answers 3


To expand on Mark's answer, there's not much (generally) available in the way of filters in the default WordPress widgets (except for perhaps widget_text).

But adding your own custom widget is easy - put this in your functions.php:

add_action("widgets_init", "my_custom_widgets_init");

function my_custom_widgets_init(){

Then you simply want to copy the existing categories widget from wp-includes/widgets/class-wp-widget-categories.php to my_widget.php in your theme, and change the class name to the same name as that used in the call to register_widget() above.

Then make whatever changes you like! I suggest changing the title too so you can distinguish it from the default Categories widget.


You can override the default WordPress widgets by extending them. The code for the default Categories widget can be found on the following link: https://developer.wordpress.org/reference/classes/wp_widget_categories/widget/

and below is an example code how you can override the output of the widget.

Class My_Categories_Widget extends WP_Widget_Categories {
    function widget( $args, $instance ) {
        // your code here for overriding the output of the widget

function my_categories_widget_register() {
    unregister_widget( 'WP_Widget_Categories' );
    register_widget( 'My_Categories_Widget' );
add_action( 'widgets_init', 'my_categories_widget_register' );
  • 2
    And the reason I didn't offer that as an option is that you might want the original behavior at some point, and with your solution you just lose the ability to get it. Jun 15, 2016 at 9:26
  • 1
    Yes, if you want to have the default widget as it is, it's better to register a totally new widget. codex.wordpress.org/Function_Reference/register_widget Jun 15, 2016 at 9:37

You do not need to create a complete new widget to do what you need to do. As I read your question, you are just interested in changing how the categories are displayed on the front end. There are two functions that displays the categories on the front end

This all depends on what option was selected in the backend

Now, each of these two functions have a widget specific filter (widget_categories_args and widget_categories_dropdown_args respectively) which you can use to alter the arguments that should be passed to these functions. You can use this to alter the behavior of the list/dropdown. However, this may not be sufficient to do what you want.

Alternatively, each function has its own filter to completely alter the way how these functions should display their output.

They respectively are

We can use the widget_title filter to specifically target the widget only and not other instances of these functions.

In short, you can try the following: (TOTALLY UNTESTED)

add_filter( 'widget_title', function( $title, $instance, $id_base )
    // Target the categories base
    if( 'categories' === $id_base ) // Just make sure the base is correct, I'm not sure here
        add_filter( 'wp_list_categories', 'wpse_229772_categories', 11, 2 );
        //add_filter( 'wp_dropdown_cats', 'wpse_229772_categories', 11, 2 );
    return $title;
}, 10, 3 );

function wpse_229772_categories( $output, $args )
    // Only run the filter once
    remove_filter( current_filter(), __FUNCTION__ );

    // Get all the categories
    $categories = get_categories( $args );

    $output = '';
    // Just an example of custom html
    $output .= '<div class="some class">';
    foreach ( $categories as $category ) {
        // Just an example of custom html
        $output .= '<div class="' . $category->term_id . '">';
        // You can add any other info here, like a link to the category
        $output .= $category->name;
        // etc ect, you get the drift
        $output .= '</div>';
    $output .= '</div>';

    return $output;

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.