Building a grid using Sass mixins

Whilst on a train yesterday I had some time to spare, so I decided to make my own grid system. To see all the code at once check out the gist, otherwise read on to see how I put it together.

What I want from a grid system

When using a grid system I want it to be configurable and I want to be able to choose my own class names. With this in mind I created some variables for the parts that need to be configurable:

1
2
3
4
5
6
$container-width: 96% !default; // Sets the overall width
$container-max-width: 1200px !default; // Sets the max-width
$grid-base-outer-width: 940 !default; // Context
$grid-base-col-width: 60 !default; // Based on context
$grid-base-gutter-width: 20 !default; // Based on context
$grid-cols: 12 !default; // Number of columns

I’ve appended the !default flag to each variable so they can be overridden by the projects config/variables file if needed.

The basics

The first part of building a grid system is setting up the overall page container mixin:

1
2
3
4
5
6
@mixin container {
  @include clearfix;
  width: $container-width;
  max-width: $container-max-width;
  margin: 0 auto;
}

I’ve used a clearfix mixin based on Nicolas Gallagher’s micro clearfix hack. This would normally be somewhere else in the project but I’ve included it here for the sake of clarity:

1
2
3
4
5
6
7
8
9
10
11
12
@mixin clearfix {

  &:before,
  &:after {
    content: " ";
    display: table;
  }

  &:after {
    clear: both;
  }
}

To clear the columns I’m going to need a row mixin. You could use the clearfix mixin instead if you prefer, as it does exactly the same thing:

1
2
3
@mixin row {
  @include clearfix;
}

Making the columns

No grid would be complete without its columns. First I need to calculate some percentages for the grid columns and gutters:

1
2
$grid-col-width: percentage($grid-base-col-width / $grid-base-outer-width);
$grid-gutter-width: percentage($grid-base-gutter-width / $grid-base-outer-width);

Now I know what measurements I’ll be working with I can create a mixin to create the columns:

1
2
3
4
5
6
7
8
9
@mixin span-columns($cols) {
  float: left;
  width: ($grid-col-width + $grid-gutter-width) * $cols - $grid-gutter-width;
  margin-right: $grid-gutter-width;

  &:last-child {
    margin-right: 0;
  }
}

Allowing for more rows

This all works fine but it means every time I want a new row of columns I’ll need to create a new row container. In some cases this is fine, but if I’m working with a grid of thumbnails this isn’t very useful, so I created an omega mixin to clear the end of each row:

1
2
3
4
5
6
@mixin omega($nth) {

  &:nth-child(#{$nth}) {
    margin-right: 0;
  }
}

The drawback to this is that I may need to reset the omega element at a different breakpoint. For that I created another mixin:

1
2
3
4
5
6
@mixin omega-reset($nth) {

  &:nth-child(#{nth}) {
    margin-right: $grid-gutter-width;
  }
}

Usage

This grid system is all mixins. No code is output unless you choose to use it, which is as simple as including the relevant mixin when defining your layout classes. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
.page-container {
  @include container;
}

.thumbnails {
  @include row;
}

.thumbnail {
  @include span-columns(6);
  @include omega(2n);

  @media only screen and (min-width: 600px) {
    @include span-columns(4);
    @include omega-reset(2n);
    @include omega(3n);
  }
}

The class names I’ve used above are purely to illustrate how these mixins can be used. The idea is that it’s up to you to define the class names you use.

Going forward

There are many ways I could extend this grid framework, but for simple projects this has everything I need. If I wanted anything more fully-featured I would still use neat as it has everything I need in a grid system, whilst being tested and maintained by some very smart people.