Journal

Back

Build your own CSS grid using Sass 6th September 2018

We've touched on before how we refrain from using frameworks and boilerplates in our projects. Whilst beginning from Bootstrap - an effective yet overweight library - or the more simplistic HTML5 Boilerplate may initially shorten the development roadmap, they can infrequently lead to road blocks further down the line or at the very least significantly increase the size of a website's codebase. Not only that, that both the aforementioned libraries are designed to be used in conjunction with jQuery.

For instance, to include the entirety of the CSS and Javascript for Bootstrap (which, admittedly, no experienced developer would do) results in a 3.2MB codebase. And that's before you've written a single line of HTML or included an image.

With the exception of Normalize.css, all the code we write is not only bespoke, it is concise with no unnecessary styles or functions included.

Normalize.css makes browsers render all elements more consistently and in line with modern standards. It precisely targets only the styles that need normalizing.

With all that said, designers like grids and therein lies the problem. Bootstrap's grid can fit a wide range of requirements. But because of that, it will not fit everyone's design perfectly and will always have surplus code. In order to develop a pixel-perfect final product, we need to create our own grid.

This can often be a tedious and laborious task and inconvenient when changes need to be made, so we decided to knock up a Sass mixin to lighten the load. These few lines of code are all that's really needed to define your CSS grid:

 @mixin columns($name, $columns, $bp, $bp2: false) {
    @include breakpoint($bp, $bp2) {
        @for $i from 1 to $columns+1 {
            .#{$name}-#{$i} { width: calc(100% / #{$columns} * #{$i}); display: inline-block; }
            .#{$name}-push-#{$i} { margin-left: calc(100% / #{$columns} * #{$i}); }
        }
    }
}

It's easy to extend this with extra functionality as well, and then the CSS comes to life based on parameters passed into the mixin such as viewport name (desktop) total number of columns for that viewport (8) and the relevant @media queries generated by a separate Sass mixin:

@mixin columns($name, $columns, $bp, $bp2: false) {
    @include breakpoint($bp, $bp2) {
        @for $i from 1 to $columns+1 {
            .#{$name}-#{$i} { width: calc(100% / #{$columns} * #{$i}); display: inline-block; }
            .#{$name}-push-#{$i} { margin-left: calc(100% / #{$columns} * #{$i}); }
        }
        .#{$name}-half { width: 50%; display: inline-block; }
        .#{$name}-push-half { margin-left: 50%; }
        .#{$name}-one-third { width: 33.3333%; display: inline-block; }
        .#{$name}-push-one-third { margin-left: 33.3333%; }
        .#{$name}-two-thirds { width: 66.6666%; display: inline-block; }
        .#{$name}-push-two-thirds { margin-left: 66.6666%; }
        .#{$name}-full-width { width: 100%; display: inline-block; }
    }
}

@include columns(desktop, 8, m-up)
@include columns(tablet, 6, s, m)
@include columns(mobile, 2, s)

"But what about flexbox?!" I hear you cry. We interchange the use of CSS flexbox and percentage-width blocks depending upon the project and requirements. The above code can be easily modified to use flexbox instead, however we found that for this specific project the results were not totally predictable, particularly when it came to cross-browsing compatibility and the responsiveness of the site across different size viewports.

Also, flexbox is essentially for laying out items in a single dimension – in a row OR a column whereas CSS Grid is for layout of items in two dimensions – rows AND columns. There are however grid systems based on flexbox.

As things often do in the world of CSS, all this will likely change in the near future. CSS Grid is quickly gaining traction over 87% browser support at time of writing. We'll cover the ins and outs of CSS Grid Layout in a future post.