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
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:
- Adding an input field on the widget configuration form
- Updating the widget options
- 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 :)
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.
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?
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?
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 :)
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!
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
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
Hi Ed,
Sorry for the late reply and thank you for confirming that it works for you too. :)
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
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
i have this same issue.
also, it doesn’t show on all widgets
what about the widget’s ul / li / a or even adding a span tag..HELP ME OUT BRO!!
This code is only for changing the widget wrapper’s attributes, not the content of the widget itself.