WordPress.org

Ready to get started?Download WordPress

Forums

Dynamic Widget Classes for use in CSS (13 posts)

  1. Justin Tadlock
    Member
    Posted 5 years ago #

    Problem:
    I need to have dynamic classes for widgets. Let's suppose I have a single sidebar. Which widgets and the number of widgets displayed is unknown (this is for a public theme).

    I'm trying to make the widgets appear something like this:

    <div id="widget-id" class="widget-class widget-1 widget-odd">
    	Widget stuff
    </div>
    
    <div id="widget-id" class="widget-class widget-2 widget-even">
    	Widget stuff
    </div>
    
    <div id="widget-id" class="widget-class widget-3 widget-odd">
    	Widget stuff
    </div>

    Why?

    This would allow for alternating styles and other cool CSS stuff by specifically referencing widgets by class. I can't reference a particular widget because there's no way for me to know what widget a user would be using.

    What I have thus far:

    I have the basic widget setup:

    register_sidebar(array(
    	'name' => '__('Widget Name','localization'),
    	'before_widget' => '<div id="%1$s" class="%2$s">',
    	'after_widget' => '</div>',
    	'before_title' => '<h3 class="insert-header insert-title">',
    	'after_title' => '</h3>',
    	)
    );

    I wanted to add another class like this by referencing a function to generate the dynamic class:

    'before_widget' => '<div id="%1$s" class="%2$s' . my_widget_class() . '">',

    Normally, for something like posts or comments, I could do something like this, but it won't work in this situation:

    function my_widget_class() {
    
    	global $widget_num;
    
    // Widget class
    	$class = array();
    	$class[] = 'widget';
    
    // Iterated class
    	$widget_num++;
    	$class[] = 'widget-' . $widget_num;
    
    // Alt class
    	if($widget_num % 2) :
    		$class[] = 'insert-even';
    	else :
    		$class[] = 'insert-odd';
    	endif;
    
    // Join the classes in the array
    	$class = join(' ', $class);
    
    // Return the class for use in the widget
    	return $class;
    }

    I'm wondering if there's some kind of filter I'm overlooking that would handle this. Basically, I could just use a push in the right direction.

  2. Justin Tadlock
    Member
    Posted 5 years ago #

    Just giving this thread a friendly bump to see if anyone might know of a possible solution or where to look.

    I'm still plugging away at it, but I don't have anything useful to add.

  3. Ptah Dunbar
    Member
    Posted 5 years ago #

    Running the code results in widget-1 insert-even on all widgets.

    If we could probably get $widget_num to count how many widgets are loading on a page, that should solve the numbering/even-odd problem.

    I can understand the even/odd but why add another widget-X class? The widgets already has unique identifiers. Another solution would be to add <div id="%1$s" class="<strong>widgets</strong> %2$s">

  4. Ptah Dunbar
    Member
    Posted 5 years ago #

    - minus the strong tags. woops.

  5. Justin Tadlock
    Member
    Posted 5 years ago #

    Yep, the widget-1 insert-even is the problem here.

    The extra class of widget-x was added for being able to target more than odd/even. Let's say I wanted to alternate the colors every three widgets (red, white, blue background). I could style it by targeting widget-1, widget-2, and widget-3. Of course, I'd still run into the problem of not knowing how many widgets are in use with the CSS.

    The major thing right now is just getting the number of widgets that are shown on the page, which I've just about run out of ideas on.

  6. Justin Tadlock
    Member
    Posted 5 years ago #

    Here's what I have that's working with one problem. I'd be very much appreciative if anyone could point me in the right direction.

    This function gives an alternating background of:

    .widget-even
    .widget-alt
    .widget-odd

    It also numbers the widgets:

    .widget-1
    .widget-2

    The problem is that it needs to be reset for each new dynamic_sidebar() because the alternating/numbering carries over from one sidebar to the next.

    add_filter('dynamic_sidebar_params','custom_widget_counter');
    
    function custom_widget_counter($params) {
    
    	global $my_widget_num;
    
    	$my_widget_num++;
    	$class = 'class="widget-' . $my_widget_num . ' ';
    
    	if($my_widget_num % 2) :
    		$class .= 'widget-even ';
    		$class .= 'widget-alt ';
    	else :
    		$class .= 'widget-odd ';
    	endif;
    
    	$params[0]['before_widget'] = str_replace('class="', $class, $params[0]['before_widget']);
    
    	return $params;
    }
  7. Daniel Tan aka BoltClock
    Member
    Posted 5 years ago #

    I'm wondering if there's some kind of filter I'm overlooking that would handle this.

    I worked it out: it's the dynamic_sidebar_params filter. Change your function to the following:


    function my_widget_class($params) {
    global $widget_num;

    // Widget class
    $class = array();
    $class[] = 'widget';

    // Iterated class
    $widget_num++;
    $class[] = 'widget-' . $widget_num;

    // Alt class
    if ($widget_num % 2) :
    $class[] = 'insert-even';
    else :
    $class[] = 'insert-odd';
    endif;

    // Join the classes in the array
    $class = join(' ', $class);

    // Interpolate the 'my_widget_class' placeholder
    $params[0]['before_widget'] = str_replace('my_widget_class', $class, $params[0]['before_widget']);
    return $params;
    }

    (I fixed the confusion between odd and even, BTW.)

    Your function is actually being called within register_sidebar(), so there isn't any loop involved. We'll use a placeholder CSS class called 'my_widget_class' instead. Change the 'before_widget' string to:


    'before_widget' => '<div id="%1$s" class="%2$s my_widget_class">',

    Then add this to the dynamic_sidebar_params filter:


    add_filter('dynamic_sidebar_params', 'my_widget_class');

    I tried it on my theme and it works flawlessly. For multiple sidebars, though, $widget_num will continue to increment instead of resetting at the first widget of a different sidebar.

    Since you only have one sidebar, that shouldn't be a problem. Let me know if you have any issues with this.

  8. Daniel Tan aka BoltClock
    Member
    Posted 5 years ago #

    I like to nitpick on my formatting: although the function code is readable and parseable by PHP I'm going to paste it again...

    function my_widget_class($params) {
    	global $widget_num;
    
    	// Widget class
    	$class = array();
    	$class[] = 'widget';
    
    	// Iterated class
    	$widget_num++;
    	$class[] = 'widget-' . $widget_num;
    
    	// Alt class
    	if ($widget_num % 2) :
    		$class[] = 'insert-odd';
    	else :
    		$class[] = 'insert-even';
    	endif;
    
    	// Join the classes in the array
    	$class = join(' ', $class);
    
    	// Interpolate the 'my_widget_class' placeholder
    	$params[0]['before_widget'] = str_replace('my_widget_class', $class, $params[0]['before_widget']);
    	return $params;
    }
  9. Justin Tadlock
    Member
    Posted 5 years ago #

    I've worked out that much of the problem here, which does the same thing your code does using the dynamic_sidebar_params:
    http://wordpress.org/support/topic/206194?replies=5#post-957593

    Now, what I'm trying to do is get it to reset for each sidebar.

  10. ty
    Member
    Posted 4 years ago #

    Thanks much for the headstart you've given with your code. I'm going to use it for something similar. Did you figure out how to reset the count for multiple sidebars? Why not just explicitly reset your global variable to 0, immediately after calling any dynamic sidebar? You could employ a second filter to do this for you.

    add_filter('dynamic_sidebar','custom_widget_counter_reset', 99);
    add_filter('dynamic_sidebar_params','custom_widget_counter');
    function custom_widget_counter_reset($text) {
       global $my_widget_num;
       $my_widget_num = 0;
       return $text;
    }

    I haven't tested this but it (or something similar to it) should work. I'm not sure the order of the filters, but you could otherwise reset it immediately prior to calling any dynamic sidebar if this approach doesn't work.

    BTW, you've got a great blog going there Justin (greenshady), I've come across it several times while googling solutions to my would-be WP problems :)
    peace~

  11. hedonbutch
    Member
    Posted 4 years ago #

    Would it be possible to break this whole idea down to a noob level for those of us that are apparently slow-witted?

    I was hoping to make the widgets in my sidebar have alternating background colors so that they were more distinct. I can see here that you solved the problem, but I don't know where to insert the code you have posted.

    I do know how to style the classes in the CSS though so you don't need to worry about that part.

    A little more guidance on placing the code would be really appreciated. Thanks.

  12. neologan
    Member
    Posted 4 years ago #

    i would also like help on how to insert this code to make it all work.

    Or someone could get this working as a plugin?

  13. neologan
    Member
    Posted 4 years ago #

    may as well post this. This can be done using css: http://inspectelement.com/demos/selectors/alternaterow/

    view source for how it's done.

Topic Closed

This topic has been closed to new replies.

About this Topic

Tags