Add Custom Class(es) to ANY Widget

WordPress has a powerful API for creating, configuring and displaying widgets, but one thing I really need is the ability to add custom class(es) to the widgets. Every widget should usually come with its own classname, which will be printed when the sidebar is being displayed. So, assuming you’ve used the correct method for registering sidebar, you can add these following functions to your theme/plugin to provide the user the ability to add custom class(es) to the widgets.

Update #2
I’m retiring KC Widget Enhancements and have written an new plugin that only provides this functionality. For now, you can get it from GitHub. Please note that you will need to re-enter you widget attributes, because the attibutes are saved with different keys.

Update
I’ve created a plugin for this so you won’t need to edit your theme/plugin files anymore :) Download it from WordPress plugins repo.

There are three steps involved:

  1. Adding an input field on the widget configuration form
  2. Updating the widget options
  3. Adding our custom class(es) to the widget markup

Adding an input field on the widget configuration form

function kc_widget_form_extend( $instance, $widget ) {
	if ( !isset($instance['classes']) )
		$instance['classes'] = null;

	$row = "<p>\n";
	$row .= "\t<label for='widget-{$widget->id_base}-{$widget->number}-classes'>Additional Classes <small>(separate with spaces)</small></label>\n";
	$row .= "\t<input type='text' name='widget-{$widget->id_base}[{$widget->number}][classes]' id='widget-{$widget->id_base}-{$widget->number}-classes' class='widefat' value='{$instance['classes']}'/>\n";
	$row .= "</p>\n";

	echo $row;
	return $instance;
}
add_filter('widget_form_callback', 'kc_widget_form_extend', 10, 2);

The kc_widget_form_extend() simply adds a new input field on the widget configuration form. You can add another field here if you’re feeling adventurous :)

Updating the widget options

function kc_widget_update( $instance, $new_instance ) {
	$instance['classes'] = $new_instance['classes'];
	return $instance;
}
add_filter( 'widget_update_callback', 'kc_widget_update', 10, 2 );

The kc_widget_update() functions added a new option to the widget which will be saved to the database when you hit the Save button.

Adding our custom class(es) to the widget markup

function kc_dynamic_sidebar_params( $params ) {
	global $wp_registered_widgets;
	$widget_id	= $params[0]['widget_id'];
	$widget_obj	= $wp_registered_widgets[$widget_id];
	$widget_opt	= get_option($widget_obj['callback'][0]->option_name);
	$widget_num	= $widget_obj['params'][0]['number'];

	if ( isset($widget_opt[$widget_num]['classes']) && !empty($widget_opt[$widget_num]['classes']) )
		$params[0]['before_widget'] = preg_replace( '/class="/', "class=\"{$widget_opt[$widget_num]['classes']} ", $params[0]['before_widget'], 1 );

	return $params;
}
add_filter( 'dynamic_sidebar_params', 'kc_dynamic_sidebar_params' );

The last step is to modify the widget’s markup. When you call the dynamic_sidebar() function, WordPress prepares the markup for every widget, including its id and classes. It took me a while to figure out a way to modify the markup and I’m not really sure that it’s the best one, but it sure does the job :)

First, we pull all registered widgets from the global $wp_registered_widgets variable. Since we don’t want to modify all widgets, we need to filter the one we want using the $params variable that WordPress passed to our function. When we found the widget, we’ll check if it has custom class(es) added, and then add them to its markup.

Now you can use those custom classes in your stylesheet to give your widgets some unique look n’ feel :)

22 Comments

  1. Thanks for the post. I’ve been looking earnestly for this feature and have been unsuccessful finding a solution. The “Widget Classes” plug-in looked to be the solution but it doesn’t appear to work with v3.0.

    While I don’t get an errors with your solution, I’m also not getting any custom classes added to my markup.

    Am I to simply paste these three sections of code into my theme’s custom functions.php file? If so, that’s what I’ve done but to no avail. I do see the input field on widgets and am able to enter a custom class but step 3 doesn’t seem to work for me. Any thoughts? I’ve updated to the latest 3.03 version as of today.

    Reply

    1. Yes, all you need to do is to add those codes to your functions.php file. But you have to make sure that your theme used the right method for registering the sidebar(s). Could you paste the code here?

      Reply

      1. Ha, no need to paste the code because I got it working based simply on what you said and I figured out what I did wrong.

        I had pasted your code at the top of my functions.php file BEFORE registering the sidebars. I had customized my theme’s registering of sidebars by modifying that code within my functions.php but then made the obvious mistake of calling your stuff first. Thank you.

        Amazing what a night’s sleep and and a good comment from you will do. Thank you so much, really. I’ve been dying for this feature that, quite frankly, I’m surprised was so hard to find a solution to.

        Any chance you’d be compelled to get this into a plugin format?

        Reply

        1. I’m glad you finally got it working David. And yes, I’m planning on making this as a component of my widgets plugin. Hopefully I can release the plugin in not-so-distance future :)

  2. Thanks for this. I have been banging my head over this since 9 this morning. You saved the day. Thank you Thank you Thank you!

    Reply

  3. I love the approach and after reviewing the code, I am getting what is happening. However, I can not get this to work.

    It does provide the field for the custom classes, and I am finding that the class was added to the database. However, it is not outputting in the HTML.

    I have also made sure I am registering the sidebar properly (even replacing what I have with the exact stuff from the codex) and calling your functions AFTER registering my sidebars. But it does not output the class in the HTML.

    Any thoughts? I REALLY need this functionality for several websites I am building now, and in the future. Any help will be GREATLY appreciated.

    Using WP 3.0.4

    Reply

  4. Nevermind!

    I found the problem.
    Before using your solution, I tried to use the Shiba Widget plugin, as it promised this option as well. It did not work well at all and was confusing, so I removed it. However, it had added filters to the widgets that were overridding or conflicting with yours. I just went into the database on my dev site and flushed the entire database to start over with a fresh install, and with your code added, it worked perfectly!

    Since I did a backup of the database before flushing, now I need to go in and try to remove the filters added by this plugin so that I can use this on the dev site. Either that, or simply start the dev file over!

    Thanks for a great piece of code!
    Ed

    Reply

    1. Hi Ed,

      Sorry for the late reply and thank you for confirming that it works for you too. :)

      Reply

  5. [...] 'kc_dynamic_sidebar_params' ); Credit: This is a modified version of the code found at http://kucrut.org/2010/11/add-custom-classes-to-any-widget/. The modification was to allow the programmer to pre-populate the css classes the designer added to [...]

    Reply

  6. I have actually taken your code and made a modification to it that allows the developer to add predetermined classes, and shows them in a drop down box rather than allowing users to add classes on the fly. This is a great option when you are doing a custom design and want to give the client options for different widget styles on the fly, without opening up the option to mess with the design itself. Of course, any client that actually understands the code can make changes, but highly unlikely for most.

    Posted modification at http://ednailor.com/2011/01/24/adding-custom-css-classes-to-sidebar-widgets/ with a link back here for credit on the original code!

    Thanks again!
    Ed

    Reply

  7. Kucrut,

    I have found that when using the Widget Logic plugin, it completely disables the custom classes. The widgets still show the data, but the data is not displayed in the HTML output. Any way you can look at this and see what is going on? I am looking too, and maybe we can find it together somehow. If you find something, can you email me directly?

    Widget Logic is found at http://wordpress.org/extend/plugins/widget-logic/

    Thanks
    Ed

    Reply

    1. i have this same issue.

      also, it doesn’t show on all widgets

      Reply

  8. what about the widget’s ul / li / a or even adding a span tag..HELP ME OUT BRO!!

    Reply

    1. This code is only for changing the widget wrapper’s attributes, not the content of the widget itself.

      Reply

  9. [...] 方法来源于《Add Custom Class(es) to ANY Widget》 [...]

    Reply

  10. Thanks for this! This has been extremely handy, I’m developing this massive widget-based layout manager and I needed to be able to place span and border options on any widget. I knew it was possible because I’ve seen plugins like Widget Logic do it. I’m sure this saved me a whole lot of greif trying to figure it out myself.

    Thanks

    Reply

    1. You’re very welcome Eddie!

      Reply

  11. Thanks for post. This code add fields for all widget, but I want use it only for widget areas with names ‘undermenu’ and ‘overfooter’. What can I do?

    Reply

    1. Dzikri Aziz 2013/07/06 at 4:55 am

      Hi Leon,

      Unfortunately – AFAIK – there’s no easy way to know in which sidebar the current widget form is being displayed. However, I think you can hide the fields via CSS easily :)

      Reply

  12. This is fantastic! How can I place the field for additional classes at the bottom after the default fields of the widget?

    Reply

    1. Dzikri Aziz 2013/10/20 at 8:56 am

      Jordan, please use the new plugin (see Update #2 above).

      Reply

  13. […] while ago, I wrote about how you can add custom classes to your widgets. I’ve also created a plugin that’s available in WPORG but haven’t been updated in […]

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>