Proportional Grids

I’ve been working with responsive design for a year or two now, and one thing that has always been a bit of an issue is flexible grids. It’s obvious that as screen size gets larger, layout must change. How do you best handle that?

The problem

Having tried many existing approaches, a lot of them seem a bit cumbersome and you end up re-defining a lot of CSS over and over as you go up through the breakpoints. This is especially true if you have percentage gutters – 10% of a mobile phone is a lot smaller than 10% of a desktop monitor. Nesting grids is also difficult, as you end up having to do all sorts of calculations to make gutters equal. Things are made easier with preprocessors Less and Sass able to do those calculations for you, but all those numbers seem a bit overkill.

My solution

I have used the CSS property box-sizing to create a solution that allows for fixed gutters (ems/rems) mixed with fluid columns. The distance between columns will remain equal at every breakpoint, in relation to the base font-size.

Columns are defined by proportion e.g. one half, one third, two thirds and can be easily re-used as many times as you like, even when nested. I have also added a CSS-only fallback for IE7 and below.

Check out the demo

A shout must go out to Harry Roberts for pointing me in the right direction with the idea!


How it works

There is no class="first" to add to any of your columns because the gutter on the first column has been negated like so:

.grid-wrap {    
    margin-left: -3em; /* the same as your gutter */
    overflow: hidden;
    clear: both; }
   
.grid-col {
    float: left;
    padding-left: 3em; /* this is your gutter between columns */
    width: 100%;
    -webkit-box-sizing: border-box;
       -moz-box-sizing: border-box;
            box-sizing: border-box; }

Classes are then used on each column to determine which proportion is taken at which breakpoint:

Column 1

Column 2

In this example, each grid-col starts life as a single column. The class bp1-col-one-half means that column becomes one-half at breakpoint 1. bp2-col-two-thirds means it becomes two-thirds at breakpoint 2. And so on.

It’s that simple, one grid system, one set of classes, wherever you want!

bp2-col is simply a namespace / prefix for that breakpoint. You can call these whatever you like but I prefer to use numbers rather than being stuck to a device e.g. tablet-col.

Internet Explorer

Obviously IE8 and below does not support @media and IE7 and below does not support box-sizing. But fear not, I’ve added an IE-specific stylesheet which repeats everything that appears inside a media query (for IE8) and creates a slightly modified grid for IE7 and below. Both receive a fixed-width 960px wide container as these browsers will be used on desktop machines.


What’s included

Examples of 6 different grid configurations including blocked, nested, and one with smaller gutters (just by adding a single class to .grid-wrap). Sass files are provided which makes it far easier to compile your grid by including one mixin per breakpoint and then repeating each one in ie.scss.

Give it a try and if you have any comments, questions or put the grids to use anywhere — let me know below or hit me up on Twitter.

Download on Github

Finished reading, formed an opinion?

Discussion

  1. Rizky Syazuli

    #

    the meta viewport tag on the demo page is still commented. is that intentional?

  2. Steve Lacey

    Steve Lacey

    #

    This sounds good but does mean that unless you’re happy (and able) to wrap your content in 2 additional levels of nesting (the wrapper and the columns) you wouldn’t be able to apply any styling to your columns, due to the padding-left.

    Is there a way to make this work with margin-left instead?

  3. Matt Berridge

    #

    @Rizky – it’s commented out so that when viewing the demo on an iPhone, you can see all the grid examples I’ve set up rather than everything being in one column. If you’re using the grids in production you should uncomment the meta tag.

    @Steve – naturally having to nest quite a few elements could be seen as a trade-off. I think it’s a good compromise given the simplicity of the concept and the CSS in particular. I find it’s good practice to separate layout and style even if it means using an extra element here or there.

    Obviously if it’s not possible for your particular projet then you could look at other grid systems. Unfortunately you can’t use margin because that lies outside of the box model and is unaffected by box-sizing. I have seen some great grids using margin e.g. Shiro / Griddle. Maybe check those out?

  4. Adamo Maisano

    Adamo Maisano

    #

    I love the concept. We’ve been using box-sizing much more often these days – it’s very useful. One thing though – I’ve got a pretty robust system here and the demo really hangs when resizing – as if there’s way too much processing going on. Is it just because you’ve packed so much responsive goodness on one page?

  5. Matt Berridge

    #

    @Adamo – I’ve not noticed any slow rendering but it may be due to processing of the maths behind all the different grids / re-flowing a large amount of text? Can’t see any other reason for it as it’s all vanilla CSS.

  6. Dennis Johnsen

    Dennis Johnsen

    #

    This is a great addition to the stuff Harry Roberts did. I’m gonna implement this into my own framework soon. Though as mentioned above, this new border-box method has a flaw; it does not support 100% width/height styling due to padding. Could we bypass this padding by adding a positioned element within the column?

    Anyhow, great work!

  7. Matt Berridge

    #

    @Dennis – If you wanted to add styling to the containing grid column I suggest you add a nested element as shown in the Blocked grid example. Not sure if that’s entirely what you meant?

  8. Dennis Johnsen

    Dennis Johnsen

    #

    Not entirely what I meant.
    I meant if I would like the whole column (including the padding) colored. But I recon I should just make a .no-gutter class (like your half-gutter) to obtain that?