Add class to before_widget from within a custom widget

I have a simple custom widget that asks for its width (that is used later in the front end). The width field is a select dropdown, so a user have predefined options.

I will have many instances of my widget, each will have its own width setup.

Read More

Now, in my widget code I have the following code:

echo $before_widget;

which results in:

<div class="widget my" id="my-widget-1"></div>

What I’d like to do is somehow hook into $before_widget and add my own class (the specified width from the select dropdown). So, I want the following markup:

<div class="widget my col480" id="my-widget-3"></div>

And if there is no class specified then I want to add class="col480".

How do I achieve this?

Thanks for help!
Dasha

Related posts

Leave a Reply

5 comments

  1. Aha, so the $before_widget variable is a string representing div element: <div class="widget my" id="my-widget-1"> . So I checked the $before_widget for the “class” sub-string and added my $widget_width value to it.

    The code is from my custom widget file:

    function widget( $args, $instance ) {
      extract( $args );
      ... //other code
    
      $widget_width = !empty($instance['widget_width']) ? $instance['widget_width'] : "col300";
      /* Add the width from $widget_width to the class from the $before widget */
      // no 'class' attribute - add one with the value of width
      if( strpos($before_widget, 'class') === false ) {
        // include closing tag in replace string
        $before_widget = str_replace('>', 'class="'. $widget_width . '">', $before_widget);
      }
      // there is 'class' attribute - append width value to it
      else {
        $before_widget = str_replace('class="', 'class="'. $widget_width . ' ', $before_widget);
      }
      /* Before widget */
      echo $before_widget;
    
      ... //other code
    }
    

    I wanted to add my $widget_width variable to the widget div element within my own widget code (while I had an easy access to the $widget_width variable).

    Hope that makes sense and will help someone.

    Thanks, Dasha

  2. you can use dynamic_sidebar_params filter hook to find your widget and add your classes to it:

    add_filter('dynamic_sidebar_params', 'add_classes_to__widget'); 
    function add_classes_to__widget($params){
        if ($params[0]['widget_id'] == "my-widget-1"){ //make sure its your widget id here
            // its your widget so you add  your classes
            $classe_to_add = 'col480 whatever bla bla '; // make sure you leave a space at the end
            $classe_to_add = 'class=" '.$classe_to_add;
            $params[0]['before_widget'] = str_replace('class="',$classe_to_add,$params[0]['before_widget']);
        }
        return $params;
    } 
    
  3. Another way I found to add a class for a custom widget is to use the the ‘classname‘ key of your construct function like in:

    class My_Widget_Class extends WP_Widget {
    // Prior PHP5 use the children class name for the constructor…
    // function My_Widget_Class()
           function __construct() {
                $widget_ops = array(
                    'classname' => 'my-class-name',
                    'description' => __("Widget for the sake of Mankind",'themedomain'),
                );
                $control_ops = array(
                    'id_base' => 'my-widget-class-widget'
                );
       //some more code after...
    
       // Call parent constructor you may substitute the 1st argument by $control_ops['id_base'] and remove the 4th.
                parent::__construct(@func_get_arg(0),@func_get_arg(1),$widget_ops,$control_ops);
            }
    }
    

    And be sure to use default ‘before_widget‘ in your theme or if you use register_sidebar() in function.php, do it like this:

    //This is just an example.
    register_sidebar(array(
              'name'=> 'Sidebar',
                'id' => 'sidebar-default',
                'class' => '',//I never found where this is used...
                'description' => 'A sidebar for Mankind',
                'before_widget' => '<aside id="%1$s" class="widget %2$s">',//This is the important code!!
                'after_widget' => '</aside>',
                'before_title' => '<h3>',
                'after_title' => '</h3>',
            ));
    

    Then on every instances of your widget, you will have the class ‘widget my-class-name’ like this:

    <aside class="widget my-class-name" id="my-widget-class-widget-N"><!-- where N is a number -->
      <h3>WIDGET TITLE</h3>
      <p>WIDGET CONTENT</p>
    </aside>
    

    You may also call the parent constructor first and then append whatever class name you want :

    class My_Widget_Class extends WP_Widget {
        // Better defining the parent argument list …
        function __construct($id_base, $name, $widget_options = array(), $control_options = array())
        {    parent::__construct($id_base, $name, $widget_options, $control_options);
             // Change the class name after
             $this->widget_options['classname'].= ' some-extra';
        }
    }
    
  4. first add a custom placeholder class in the constructor

    <?php
    public function __construct() {
       $widget_ops  = array(
          'classname'                   =>; 'widget_text eaa __eaa__', //__eaa__ is my placeholder css class
          'description'                 =>; __( 'AdSense ads, arbitrary text, HTML or JS.','eaa' ),
          'customize_selective_refresh' =>; true,
       );
       $control_ops = array( 'width' =>; 400, 'height' =>; 350 );
       parent::__construct( 'eaa', __( 'Easy AdSense Ads &amp; Scripts', 'eaa' ), $widget_ops, $control_ops );
    }
    ?>
    

    Then replace it with the class/es of your choice based on the widget options like this

    <?php
    if ( $instance['no_padding'] ) {
       $args['before_widget'] = str_replace( '__eaa__', 'eaa-clean', $args['before_widget'] );
    }
    ?>
    

    You can find the details with example at
    http://satishgandham.com/2017/03/adding-dynamic-classes-custom-wordpress-widgets/

  5. You can try this filter:

    /**
     * This function loops through all widgets in sidebar 
     * and adds a admin form value to the widget as a class name  
     *  
     * @param array $params Array of widgets in sidebar
     * @return array
    */
    
    add_filter( 'dynamic_sidebar_params', 'nen_lib_add_class_to_widget' );
    function nen_lib_add_class_to_widget( $params )
    {
        foreach( $params as $key => $widget )
        {
            if( !isset($widget['widget_id']) ) continue;
    
            // my custom function to get widget data from admin form (object)
            $widget_data = nen_get_widget_data($widget['widget_id']) ;
    
            // check if field excists and has value
            if( isset($widget_data->wm_name) && $widget_data->wm_name )
            {
                // convert and put value in array
                $classes = array( sanitize_title( $widget_data->wm_name ) );
    
                // add filter, to be able to add more
                $classes = apply_filters( 'nen_lib_add_class_to_widget' , $classes , $widget['widget_id'] , $widget , $widget_data  );
    
                // get 'before_widget' element, set find and replace
                $string     = $params[$key]['before_widget'];
                $find       = '"widget ';
                $replace    = '"widget '.implode( ' ' , $classes ).' ';
    
                // new value
                $new_before = str_replace( $find , $replace , $string ) ;
    
                // set new value
                $params[$key]['before_widget'] = $new_before;
            }
        }
        return $params;
    }