Automatic Columns for Widget Areas

In this tutorial, we will cover how to automatically (and responsively) split a widget area into columns. The number of columns will automatically be calculated based on the number of widgets in the widget area. It’s really pretty simple.

Count the widgets

First, let’s start with the function we will use to calculate the number of widgets.

function widget_count( $widget_area_id ) {
	$widget_areas = wp_get_sidebars_widgets();

	if( empty( $widget_areas[$widget_area_id] ) ) {
		return false;
	} else {
		return count( $widget_areas[$widget_area_id] );
	}
}

Display the widget area

Next we need to display the widget area. For this example, we’ll work with a widget area with an ID of “footer”.

Please note: the widget area must be registered elsewhere. I’ve left it out of this tutorial because we’re focusing on the automatic columns, not setting up standard widget areas.

if ( is_active_sidebar( 'footer' ) ) {
	$widget_count = widget_count('footer');
	?>
		<div class="widget-columns widget-count-<?php echo $widget_count; ?>">
			<?php dynamic_sidebar( 'footer' ); ?>
		</div><!--.widget-columns-->
	<?php
}

First we check if the widget area is active, then use the widget_count() function to find the number of widgets in our widget area, and finally use that number in our widget class name.

Style the widget area

Lastly, we need to write the styles that take the class names we created and create a responsive layout.

.widget-columns .widget {
	padding: 0 25px;
}

@media (min-width: 900px) {

	.widget-columns.widget-count-2 .widget,
	.widget-columns.widget-count-4 .widget,
	.widget-columns.widget-count-5 .widget {
		float: left;
		width: 50%;
	}

	.widget-columns.widget-count-3 .widget,
	.widget-columns.widget-count-6 .widget {
		float: left;
		width: 33.333333333%;
	}
	
	.widget-columns.widget-count-4 .widget:nth-child(odd),
	.widget-columns.widget-count-5 .widget:nth-child(odd),
	.widget-columns.widget-count-6 .widget:nth-child(3n+4) {
		clear: left;
	}

	.widget-columns.widget-count-5 .widget:last-child {
		margin-left: 25%;
	}
}

@media (min-width: 1140px) {

	.widget-columns.widget-count-4 .widget {
		float: left;
		width: 25%;
	}

	.widget-columns.widget-count-5 .widget {
		float: left;
		width: 20%;
	}

	.widget-columns.widget-count-6 .widget {
		float: left;
		width: 16.666666667%;
	}

	.widget-columns.widget-count-4 .widget:nth-child(odd),
	.widget-columns.widget-count-5 .widget:nth-child(odd),
	.widget-columns.widget-count-6 .widget:nth-child(3n+4) {
		clear: none;
	}

	.widget-columns.widget-count-5 .widget:nth-child(odd) {
		margin-left: 0;
	}
}

We start by giving every widget some padding so the text doesn’t touch between widgets. We also set box-sizing to border-box so that the padding is included in the calculated width of the element. This allows us to have to 50% wide columns without the padding pushing us over a total width of 100%.

Next we have the styles for tablet screen sizes. For widget areas with 2, 4, and 5 widgets, we create 2 columns by setting the widget width to 50% and floating all widgets to the left. For widget areas with 3 and 6 widgets, we create 3 columns by setting the width to 33.333333333% and once again floating all widgets to the left. At this point, widget areas with 4 or 5 widgets are being displayed in the two column layout and widget areas with 6 widgets are being displayed in the 3 column layout. It’s not until the desktop size that they will get their full number of columns. At the tablet size, we make sure they properly collapse into rows by specifying which widgets must clear the previously floated elements. Finally, we center the last widget when there are 5 widgets in a two column layout.

For desktop screen sizes, we define the 4, 5, and 6 column layouts, remove the clearing rules we used for breaking things into rows at the tablet size, and remove the left margin we used to center the last widget in a widget area with 5 widgets at the tablet size.

And there you have it. Automatically generated columns for widget areas. That wasn’t so bad, was it?