Development | 02.28.2014

Responsive Grid Column Resets

Since the release of Bootstrap 3.0, developers have been able to take advantage of the framework’s grid mixins to create their own custom grids. Semantically, this has its advantages as your code no longer needs to be cluttered the standard gird class names, such as .col-sm-8. Instead, you can now selectively target the elements you want to appear as a grid using class names that contextually make sense:

less
#main {
	.make-row();
}
#primary {
	.make-sm-column(9);
}
#secondary {
	.make-sm-column(3);
}

This is perfect for instances when you only have to deal with a single row of columns for wider screens that changes to a stacked layout for mobile devices, such as a page’s main content section and a sidebar. However, you may run into issues when your try to arrange multiple rows of elements of varying heights, such as a grid of differently-sized images. Since all elements in the grid are simply floating left, they could potentially get “caught” on taller elements from the previous row, preventing the new row from starting flush on the left edge.

Responsive Column Reset

The Bootstrap documentation recommends using what they call a responsive column reset. By adding a clearing div between rows, it’ll guarantee that each new row will begin flush against the left edge.

These responsive column resets can be programmatically added when looping through your grid elements during output:

php
for($i = 0; $i < count($elements); $i++) {
	if($i > 0 && $i % 4 == 0) echo '<div class="clearfix hidden-xs"></div>';
	echo $element[$i];
}

Unfortunately, this brings us back to relying on unsemantic class names on empty divs that serve no purpose other than keeping rows separate. What can we do to avoid this?

The :nth-child Selector

Possibly, the cleanest solution would be to target every nth child of the grid and set it to clear left using CSS’ :nth-child selector:

css
ul li:nth-child(4n+1) {
	clear: left;
}

This is great as long as you don’t need to account for older browsers that don’t support the :nth-child selector.

Manual nth Child Designation

An alternative method for targeting every nth child in a group of elements is to programmatically add classes during output:

php
for($i = 0; $i < count($elements); $i++) {
	echo '<li class="'.($i % 4 == 0 ? 'new-row' : '').'">'.$element[$i].'</li>';
}

What this does is add the .new-row class to every 4n+1 element, allowing you to set them to clear left, resetting the row:

css
ul li.new-row {
	clear: left;
}

Responsive Grid Breakpoints

Expanding on these approaches, you can selectively target break points in your custom grid system based on device width using media queries. For example, if you wanted a two column layout for small devices that transforms into a four column grid for larger devices using the :nth-child method:

css
ul li:nth-child(2n+1) {
	clear: left;
}
@media (min-width: 768px) {
	ul li:nth-child(2n+1) {
		clear: none;
	}
	ul li:nth-child(4n+1) {
		clear: left;
	}
}

For older browsers, as before, you’ll need to add the targeting classes manually on output. This could become somewhat complex as some elements would qualify for multiple classes. It may be useful to create a function to assign the classes based on the element’s index:

php
function getColResetClasses($index) {
	$classes = array();
	if($index == 0) return $classes;
	for($i = 2; $i <= 12 && $i <= $index; $i++) {
		if($index % $i == 0) $classes&#91;&#93; = 'new-row-'.$i;
	}
	return implode(' ', $classes);
}

for($i = 0; $i < count($elements); $i++) {
	echo '<li class="'.getColResetClasses($i).'">'.$element[$i].'</li>';
}

The accompanying CSS would look something like this:

css
ul li.new-row-2 {
	clear: left;
}
@media (min-width: 768px) {
	ul li.new-row-2 {
		clear: none;
	}
	ul li.new-row-4 {
		clear: left;
	}
}

With my last couple of projects, I’ve been trying to avoid using the Bootstrap classes in my HTML code and incorporating the the framework’s components through LESS mixins. Using the grid system mixins helps take a significant step towards a more semantic markup and offers greater flexibility for column layouts.