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:
#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:
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:
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:
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:
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:
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:
function getColResetClasses($index) {
$classes = array();
if($index == 0) return $classes;
for($i = 2; $i <= 12 && $i <= $index; $i++) {
if($index % $i == 0) $classes[] = '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:
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.