A Simple Responsive Grid, Made Even Better With Sass

In this tutorial we're going to build a simple, responsive grid system using CSS. Once we're familiar with how it works, we'll improve it with Sass, learning some core Sass features along the way.

Getting Started With the CSS

Let's quickly examine what our grid system will look like. There are cleverer ways of building grids, ones which are less intrusive on the markup needed, but this grid gives us a great opportunity to practice simple, yet useful Sass techniques. It uses one wrapping element, then other elements within that which act as rows, then more elements within those which act as our columns.

A bit trippy, but you get the idea..

Grid.css

To begin with, all we need is a CSS file, so open up a new document in your code editor and name it "grid.css".

The first thing we're going to add is a global reset and box-sizing rule. This will make sure that padding applied to our elements is added within their calculated dimensions, giving us far more freedom for defining column widths.

This selector says; take any element whose class contains the string column- and apply the following styles. Therefore all our column elements will float left, will have a padding of 1em (this forms our gutter and some vertical space) and will fill 100% of the viewport width (again, we're working mobile first here). Lastly, the min-height: 1px makes sure that the column displays properly, even if it has no content.

Believe it or not, we now have ourselves a grid! The following markup is all we need.

Going Responsive

That's our mobile view taken care of, now let's add a media query to give us a different layout for larger screens. You'll need to determine breakpoints for your own grid, but we're going to use one arbitrary breakpoint of 30em.

@media only screen and (min-width: 30em) {
}

Any styles we place within this media query will take effect on screens of 30em and wider. We'll use this point to split up our columns into correct widths.

% Widths

How wide should each column be? That depends on how many columns we have. For this demonstration I'm going work with twelve columns, so each one should be exactly one twelfth (1/12) of the wrapper. For a column which spans two widths, it will be two twelfths, and so on. Here's what that gives us:

You'll also see that we've made the .wrapper element less than the full width of the screen and given it a max-width. Take a look what that's done to our grid.

You'll probably want to choose more appropriate padding in your own grid

Cleaning Things up With Sass

Our CSS grid works, but what would happen if we actually wanted sixteen columns in our grid? Or even more? We'd have to recalculate every column and manually enter it in our CSS file each time. Not to mention that our CSS would get longer and longer and more difficult to manage. Happily, Sass (or any other preprocessor) can help us.

Defining Variables

Sass is going to help us clean up our CSS in all sorts of ways, but the first thing we can do is extract any useful values and store them in variables. Begin by starting off a new partial called "_variables.scss"; a Sass file which won't be compiled into CSS directly, but we'll reference in our other files.

These variables give us the amount of columns we want to work with; 12 at the moment, but could easily be altered to 16, perhaps 32 (whatever you want really). We've also stored some breakpoints in variables as strings, even though we're only using one at the moment.

We'll use these shortly, but first we'll setup some mixins.

Mixins

Sass mixins are chunks of code which we can define once and then re-use elsewhere in our project. For example, we could take the very first set of rules where we setup border-box and extract most of that into a mixin. We start with:

Using Our Variables

Let's make use of some of those variables we set up, shall we? To begin with we can swap out the max-width value on the wrapper. This:

.wrapper {
width: 95%;
max-width: 65em;
}

becomes this:

.wrapper {
width: 95%;
max-width: $grid-max-width;
}

Now let's do the same with our media query. This:

@media only screen and (min-width: 30em) {

will be improved with our $breakpoint-medium variable:

@media #{$breakpoint-medium} {

Note: you'll see we wrapped our variable in #{}. This is referred to as interpolation. This is normally done if we need to output a variable within another, but it's necessary in this case because the Sass compiler trips over media queries if @media isn't directly followed by braces (). You can read more about this in Hugo Giraudel's All You Ever Need to Know About Sass Interpolation.

To use our final variable, $grid-columns, we need to make use of some more Sass functionality; loops.

Sass Loops

Our column width definitions are all exactly the same, apart from the actual values. It will be far cleaner if we output a column definition for as many columns as we need, changing the values each time. To do this we can use a Sass @for loop, which looks like this:

@for $i from 1 through 12 {
// looped content
}

This will loop over 12 iterations, and each time the value of $i will reflect that loop. We can output $i like this:

@for $i from 1 through 12 {
.column-#{$i} {
}
}

Again, you'll notice we're using #{} around $i to output the value as a string which we're appending to the .column- selector. This gives us the following when compiled:

Brilliant! Let's now use some calculations to output the correct styles within these selectors.

Sass Operators

We're doing well, but we now need to output something like the following for each selector:

.column-5 {
width: 41.66667%;
}

That column width is calculated as 100% divided by the total number of columns, multiplied by the column number. In this case 100% / 12 * 5 = 41.66667%. That's therefore the calculation we need to apply, switching out the relevant values for variables.

Throughout this process we've looked at Sass variables, mixins, placeholders, extend, loops, operators and even interpolation. This is an incredibly powerful set of features and a great start if you're just getting into Sass.

How else could you improve the grid we've built? What else would you add or even remove? Let us know in the comments!