Boostrap responsive resets and custom grids

April 26th, 2015 - Bonn

I made a pen to have an example of different approaches to deal with an unknown number of elements that have to be displayed in a specific number of columns depending on the available width.

Let's say that you are using the bootstrap grid of 12 columns, and you want to have rows with 2 elements for narrow screens and 4 for larger ones. You can try to add more content that what fits in a single row, and take advantage of the .col- classes to force it to wrap following both distributions.

.row
  .col-xs-6.col-sm-3
    | lorem
  .col-xs-6.col-sm-3
    | lorem
  .col-xs-6.col-sm-3
    | lorem
  .col-xs-6.col-sm-3
    | lorem

This might work for some heights, but once one column is taller than the others, the following ones might just get stuck to its right instead of clearing the space and starting a new visual row. To avoid this, there's an example in the boostrap guides to apply utility classes to create responsive column resets

.row
  .col-xs-6.col-sm-3
    | lorem ipsum dolor sit amet, consectetur adipisicing elit...
  .col-xs-6.col-sm-3
    | lorem
  .clearfix.visible-xs-block
  .col-xs-6.col-sm-3
    | lorem
  .col-xs-6.col-sm-3
    | lorem

This is quite nice, but it get's harder to understand when you want to apply the same technique to add more steps. If you want to go from to 2 to 4 to six, you will end up having something like this:

.row
  .col-xs-6.col-sm-3.col-md-2
    | lorem
  .col-xs-6.col-sm-3.col-md-2
    | lorem
  .clearfix.visible-xs-block
  .col-xs-6.col-sm-3.col-md-2
    | lorem
  .col-xs-6.col-sm-3.col-md-2
    | lorem
  .clearfix.visible-sm-block
  .clearfix.visible-xs-block
  .col-xs-6.col-sm-3.col-md-2
    | lorem
  .col-xs-6.col-sm-3.col-md-2
    | lorem

In these cases, it might be easier to just roll a simple grid on your own, they require just a bunch of lines and you don't need to programatically insert those clear divs with some cumbersome rules if you are working with an unknown number of elements. If we start with a grid as follows:

.grid-container
  .grid-element
    | lorem
  .grid-element
    | lorem
  .grid-element
    | lorem
  // ...

We can take care of clearing using nth-child selectors

// http://bourbon.io/docs/#clearfix
@mixin clearfix {
  &::after {
    clear: both;
    content: "";
    display: table;
  }
}

.grid-container{
  @include clearfix;
  margin-right: -15px;
  margin-left: -15px;

  .grid-element{
    min-height: 1px;
    position: relative;
    padding: 0 15px;
    @media (max-width:768px){
      float:left;
      width: 50%;
      &:nth-child(2n+1){
        clear:left;
      }
    }
    @media (min-width: 768px) and (max-width:992px){
      float:left;
      width: 25%;
      &:nth-child(4n+1){
        clear:left;
      }
    }
    @media (min-width: 992px){
      float:left;
      width: (100%/6);
      &:nth-child(6n+1){
        clear:left;
      }
    }
  }
}

A cool alternative to have these 'cleared' rows without using floats and the clear property if to turn every element into an inline-block inside those lines. This would even work with elements of random widths, besides the random heights that we had before.

It feels a little hacky, since we need to eliminate the space between the elements using negative margins, or in this case settting the font size to cero in the container and restoring it to its former value inside the columns. But then again, we use all kinds of hacks to clear floats everywhere, this one doesn't seem too bad.

.grid-container{
  font-size:0;
  margin-right: -15px;
  margin-left: -15px;

  .grid-element{
    display:inline-block;
    vertical-align: top;
    font-size: 14px;
    min-height: 1px;
    position: relative;
    padding: 0 15px;
    @media (max-width:768px){
      width: 50%;
    }
    @media (min-width: 768px) and (max-width:992px){
      width: 25%;
    }
    @media (min-width: 992px){
      width: (100%/6);
    }
  }
}

Lastly, we can rejoice in the flexbox layout to achieve the same effect, with the side benefit of getting columns of the same height

.grid-container{
  display: flex;
  flex-wrap: wrap;
  flex-direction: row;
  margin-right: -15px;
  margin-left: -15px;
  .grid-element{
    min-height: 1px;
    position: relative;
    padding: 0 15px;
    @media (max-width:768px){
      width: 50%;
    }
    @media (min-width: 768px){
      width: 25%;
    }
    @media (min-width: 992px){
      width: (100%/6);
    }
  }
}


To see all this in action:

See the Pen Boostrap responsive resets + Custom grids by Fernando Sainz (@fsainz) on CodePen.