Simple grids on the fly with Compass

So I made my grid system. It worked great.

Then I started building a site in Drupal.

It’s hardly a secret that Drupal’s markup is really terrible. I have to control my urge to run back screaming to WordPress and never leave again! But such is life. Drupal sure has it strong points and nowadys I actually mostly enjoy working with it. Having said that 4,000 divs doesn’t always make working with the front end so easy, especially if we’re working with a CSS grid.

So, I wrote a tiny mixin for SASS/Compass that can will work out your grids for you when the markup is against you:

$columns: 16;
$gridWidth: 960px;
@mixin drupalCols($rows: 4, $padding: 0 10px) {
  width: ($gridWidth / $columns) * $rows;
  float: left;
  padding: $padding;
  @include box-sizing(border-box);
}

.my-div {
  @include drupalCols(8);
}

// This becomes:
/*
.my-div {
  width: 480px;
  float: left;
  padding: 0 10px;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
*/

// You can also add more or less padding like this:

.my-div {
  @include drupalCols(4, 10px 20px 30px);
}

/*
.my-div {
  width: 240px;
  float: left;
  padding: 10px 20px 30px;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
*/

This one has fixed pixel values because the project I wrote it for is not responsive and is based on a grid 960px wide divided into 16 sections (yes 16)!

Here’s one that is responsive based on 12 columns:

$columns: 12;
$gridWidth: 100%;
@mixin drupalCols($rows: 4, $padding: 0 10px) {
  width: ($gridWidth / $columns) * $rows;
  float: left;
  padding: $padding;
  @include box-sizing(border-box);
}

.my-div {
  @include drupalCols(4);
}

// This becomes:
/*
.my-div {
  width: 33.333%;
  float: left;
  padding: 0 10px;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
*/

For the responsive one to work (if you’ve got full control of your markup) then you could use this:

@mixin clearfix {
  &:after {
    content: " ";
    display: table;
    clear: both;
  }
}

$columns: 12;
@while $columns > 0 {
  .span-#{$columns} {
    width: percentage(0.083333 * $columns);
  }
  $columns: $columns - 1;
}

$gutter: 10px;
.row-container {
  margin: $gutter 0;
  @include clearfix;
  > div {
    border-right: $gutter solid transparent;
    border-left: $gutter solid transparent;
    float: left;
    @include clearfix;
    @include box-sizing(border-box);
  }
  &:first-child {
    border-left: none;
  }
  &:last-child {
    border-right: none;
  }
}

//This produces the following:
/*
.span-12 {
  width: 100.0%;
}

.span-11 {
  width: 91.666%;
}

.span-10 {
  width: 83.333%;
}

.span-9 {
  width: 75.0%;
}

.span-8 {
  width: 66.666%;
}

.span-7 {
  width: 58.333%;
}

.span-6 {
  width: 50.0%;
}

.span-5 {
  width: 41.667%;
}

.span-4 {
  width: 33.333%;
}

.span-3 {
  width: 25.0%;
}

.span-2 {
  width: 16.667%;
}

.span-1 {
  width: 8.333%;
}

.row-container {
  margin: 10px 0;
}
.row-container:after {
  content: " ";
  display: table;
  clear: both;
}
.row-container > div {
  border-right: 10px solid transparent;
  border-left: 10px solid transparent;
  float: left;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}
.row-container > div:after {
  content: " ";
  display: table;
  clear: both;
}
.row-container:first-child {
  border-left: none;
}
.row-container:last-child {
  border-right: none;
}
*/

// Use it like this:
/*
<div>
  <div>
    ...content...
  </div>
  ...more columns
</div>
*/

If you’re wondering about support for

box-sizing: border-box;

be happily surprised: It’s supported by all major browsers, including IE8! I tend to use it liberally these days in all my projects.