Dan J Ford

Creating a CSS grid easily

March 22, 2016 by Dan J Ford

When you're creating a website, most of the time you'll want to use a grid. Instead of having to download a grid library or a massive framework such as Bootstrap, I'm going to show you how to create a small re-usable mixin that will provide you with a means of creating a grid of various column sizes.

My example will be in SCSS. If you have any requests for having examples using another preprocessor such as LESS, let me know!

Formulising the Grid

When creating a grid for myself in a previous project, I hadn't really looked into the background logic behind creating one. After thinking about the Math behind grids for a while, I realised that you could simply make a grid by multiplying the current index ( starting at 1) in a for loop with 100 divided by the total number of columns. I.e.

( 100 / $totalColumns ) * $index;

Alternatively you could also do ($index / $totalColumns) * 100

This little formula would allow you to have well sized grids with up to 100 columns (although that would probably be a bit excessive).

As an example, if you wanted to have a 12 column grid like Bootstrap and we were on the first iteration of the for loop, this formula would look like the following example, giving us a column size like we would expect for the class .col-xs-1:

( 100 / 12 ) * 1 = 8.333333333333334

Creating the mixin

So looking at what we've said previously, for our mixin, we will will want to pass it the parameter of how many columns we would want. We would then want to loop from one to the number of columns that we want.

@mixin grid( $columns ) {

  @for $i from 1 through $columns {

     // the class
     .column-#{$i} {
        width: $i;
     }

  }

}

// Usage example
.grid(12);

Using this mixin, when you compile your code, you should now get the amount of columns that you have passed to it. Now if we plug the formula from the previous step in, the width should now become a reasonably sized grid.

@mixin grid( $columns ) {

  @for $i from 1 through $columns {

     // the class
     .column-#{$i} {

         width: #{ ( 100 / $columns ) * ($i ) + '%'};

     }

  }

}

Making the Grid Work

Now you may notice, if you have already tried using the classes, that the columns aren't yet appearing along side each other. This will be because we haven't yet given the columns any styling to tell them to do this. There are multiple ways of doing this, I will show 3 ways of doing it: A hard coding approach, a easy way and a harder way.

To make the columns alongside each other, you simply need to make them float: left;.

You will also need to have your column items box-sizing set to border-box. A common way of doing this is simply applying the property to all elements, for example:

*, :after, :before {
    box-sizing: border-box;
}

Hard coded approach

The easiest, with hard coding would be to simply put all of your column stylings directly into the mixin.

@mixin grid( $columns ) {

  @for $i from 1 through $columns {

     // the class
     .column-#{$i} {

         width: #{ ( 100 / $columns ) * ($i ) + '%'};
         position: relative;
         float: left;

     }

  }

}

The Easy Way

The following way is the easiest, but can result in unexpected bugs if you don't keep track of how you name your classes. Therefore I wouldn't recommend doing this unless you are the only person working on a project. However, the nice thing about this approach is that the float and position properties aren't repeated at all i.e. they are not repeated for each individual column class.

[class^='column-'] {
  float: left;
  position: relative;
  width: 100%;
}

The reason that I don't recommend this approach is that, if you were to name a class column-background then these stylings would also be applied to that element.

The Harder Way

The harder way also involves modifying the mixin that we created earlier, however, it can be modified in such a way that the mixin will not be hardcoded by instead passing the code that we want to style the columns with using a variable.

@mixin grid( $columns, $extra ) {

  @for $i from 1 through $columns {

     // the class
     .column-#{$i} {

          width: #{ ( 100 / $columns ) * ($i ) + '%'};

          @if $extra {
             @extend %#{$extra};
          }

     }

}

%extra {
  float: left;
  position: relative;
}

// Usage example
@include grid(12, extra);

Making the Grid Responsive

Now that all of your columns are appearing inline, you probably want it so that when the screen shrinks the grid will respond appropriately and change the columns accordingly. This would involve changing the original mixin again so that we can add a unique identifier each time we call the mixin. In this example we will use bootstrap style naming conventions and call our grid columns xs, sm, md and lg.

@mixin grid( $columns, $breakpoint ) {

  @for $i from 1 through $columns {

     // the class
     .column-#{$breakpoint}-#{$i} {

         width: #{ ( 100 / $columns ) * ($i ) + '%'};

     }

  }

}

This makes it so that we can now pass our grid mixin how many columns we want and also the breakpoint we would like our code to apply to. Here is an example of using this mixin to create a responsive grid:

// Creates the grid for extra small devices
@include grid(12, xs);

// Creates the grid for small devices
@media (min-width: 768px) {
  @include grid(12, sm);
}

// Creates the grid for medium devices
@media (min-width: 992px) {
  @include grid(12, md);
}

// Creates the grid for large devices
@media (min-width: 1200px) {
  @include grid(12, lg);
}

Using LESS

Creating the LESS version of this mixin is very similar to the SCSS version. However, the one major difference (apart from the syntax) is that LESS doesn't have proper for loops. Instead we have to make the mixin use recursion, this means that the mixin will repeatedly call itself until some final condition is met.

In the following example you may notice that the formula looks a bit different for calculating the width. The formula is essentially the same however, to make it work with LESS I have used percentage which then needs to be divided by 100 to be the correct number. Another approach would be to use string interpolation, however I find this method looks cleaner.

.grid(@columns, @breakpoint, @i: 1) when (@i < @columns + 1) {

  .column-@{breakpoint}-@{i} {
    width: percentage((100 / @columns) * @i) / 100;
  }

  .grid(@columns, @breakpoint, (@i + 1));

}


// Usage example
.grid(12, xs);

Finished!

So, that concludes this tutorial, let me know if you have any problems or would like me to add to it. Thanks for reading! Here is an example of the SCSS grid in action on my codepen:

Like what I've written?