Heygrady (there's a new blog)

I don't get It.

Using SASS With the 1KB Grid System

Permalink

The 1KB CSS Grid is a simplified grid system and is one of many dozens of different grids available. I started using a personal variant of this grid system recently because it seemed like a very simple code-base to understand. A common complaint about CSS grids is that they require classes in the markup that aren't much different that simply hard-coding widths in a style attribute. Of course SASS can help remove that complaint and makes grids even more flexible. Here's a tour of the 1KB CSS Grid, modified to suit my tastes and rewritten in SASS.

UPDATE: a Github repo has been created for the 1KB-SCSS-Grid.

UPDATE: a follow up article, Compass Grid Plugin and A New Fluid Grid Option, has been posted.

UPDATE: the Github repo has been renamed to compass-grid-plugin and a Ruby Gem has been created.

For the uninitiated

Basic CSS

grid.cssGist page
.grid-1 { width: 60px; }
.grid-2 { width: 140px; }
.grid-3 { width: 220px; }
.grid-4 { width: 300px; }
.grid-5 { width: 380px; }
.grid-6 { width: 460px; }
.grid-7 { width: 540px; }
.grid-8 { width: 620px; }
.grid-9 { width: 700px; }
.grid-10 { width: 780px; }
.grid-11 { width: 860px; }
.grid-12 { width: 940px; }
.page { width: 960px; margin: 0 auto; }
.row { width: auto; margin: 0 -10px; }
.page > .row { margin: 0; }
.column { margin: 0 10px; float: left; }
.ie6 .column { display: inline; }
.box { margin-bottom: 20px; }

The above CSS is very similar to the original source with a few stylistic differences (dashes instead of underscores) and the removal of the overflow: hidden clearfix hack and IE6 hacks. My intention is to use the grid with HTML5 Boilerplate which has a better clearfix built-in (overflow: hidden isn't appealing as a clearfix hack). I've also chosen to remove IE6 from my list of supported browsers for any project that doesn't require it.

Differences

  • Remove IE6 specific hacks
  • Remove overflow: hidden clearfix hacks
  • Change .row to .page
  • Change .row .row to .row
  • Add in a .box for containers within columns
  • Rely on HTML5 Boilerplate and Modernizr for clearfix and browser targeting

Basic Example Using Only CSS

It's not immediately obvious how to piece this all together but the concepts are pretty simple.

  • .grid-# is for column widths
  • .column is for floating columns
  • .row is a column container (columns are always nested in a row)
  • .page is the main page wrapper with a full width and is horizontally centered.
grid.htmlGist page
...
<div id="container" class="page">
<header class="row">
<h1>Header</h1>
<nav></nav>
</header>
<div id="main" class="row">
<div id="left-column" class="column grid-3">Left Column</div>
<div id="main-column" class="column grid-9">
<section class="hero row">
Hero Space
</section>
<section class="row">
<article id="content" class="column grid-6">Actual Content</article>
<aside id="right-column" class="column grid-3">Right Column</aside>
</section>
</div>
</div>
<footer class="row">
<p>&copy; Copyright 2010</p>
</footer>
</div>
...

Above is a typical page using the new HTML5 container tags and based on the example HTML5 Boilerplate markup. This example is shown with hard-coded class names in the HTML. As expected, there's a page wrapper (#container ), header , #main and footer containers, and some columns in the main area. This page would create a typical 2 column layout (#left-column and #main-column ). The #main-column , as shown, has a .hero area that spans the full width and a content area is further sub-divided into 2 columns (#content and #right-column ).

On a typical site, the header and footer would probably contain their own columns and rows. The .hero is used for promotional space at the top of content. This is a typical design choice and might contain a banner or a slideshow or some introductory copy.

Personally I find the inclusion of the class names in the markup to be a little ugly. The most offensive part is the grid-3 and grid-6 , etc. This is barely different than hard-coding the width with an inline style. I prefer to use SASS mixins to remove those class names from the markup altogether and control it directly from the CSS.

Rewritten in SASS

grid.scssGist page
// Configuration
$column-width: 60px;
$gutter-width: 20px;
$columns: 12;
// Column Widths
@mixin grid($i) {
width: $column-width * $i + $gutter-width * ($i - 1);
}
@mixin grid-plus($i, $plus) {
width: $column-width * $i + $gutter-width * ($i - 1) + $plus;
}
@for $i from 1 through $columns {
.grid-#{$i} { @include grid($i); }
}
// Page, Row, Column
@mixin grid-page($i: $columns) {
@extend .clearfix;
width: $column-width * $i + $gutter-width * $i;
margin: 0 auto;
}
@mixin grid-row($page: false) {
@extend .clearfix;
width: auto;
// rows directly inside a page don't need the negative margin
@if $page {
margin: 0 0;
} @else {
margin: 0 (-$gutter-width / 2);
}
}
@mixin grid-column($i: false) {
margin: 0 ($gutter-width / 2);
float: left;
.ie6 & { display: inline; }
@if $i {
@include grid($i);
}
}
@mixin grid-column-empty($i: 1, $position: after) {
$margin: $column-width * $i + $gutter-width * $i + ($gutter-width / 2);
@if $position == after {
margin-right: $margin;
} @else {
margin-left: $margin;
}
}
.page {
@include grid-page;
}
.row {
@include grid-row;
}
.page > .row {
margin: 0;
}
.column {
@include grid-column;
}
// Box
.box {
margin-bottom: $gutter-width;
}

Writing the same thing in SASS opens up a world of possibilities. Using mixins allows the column measurements to be easily changed and opens up the possibility of removing the extra class names from the markup. This SASS file was used to generate the CSS at the top of the article.

Default Variables

  • $column-width: 60px; is the width of a sinlge column
  • $gutter-width: 20px; is the space between two columns
  • $columns: 12; is the total number of columns
  • (60px + 20px) * 12 = 960px

Grid Mixins

grid and grid-plus are simply used for setting a width on a column. grid-plus can be used to account for padding or otherwise arbitrarily altering the standard column width. This is especially useful when dealing with designers that like grids but like violating them even more.

example1.scssGist page
#column-a {
@include grid-column; // make it a column
@include grid(6); // make it 6 columns wide
}
#column-b {
@include grid-column(6); // make it a column, 6 columns wide
}
#column-c {
@include grid-column; // make it a column
@include grid-plus(6, -10px); // make it 6 columns wide, minus padding
padding: 0 5px; // mean designer broke the grid
}

The example above shows 3 equivalent ways to specify a 6-column-wide column. The shortcut grid-column mixin makes it easy to create a standard column. But in the case where a column might require border or padding , the grid-plus mixin can be used to account for the difference.

  • @include grid(<number>); is for column widths
    • @include grid-plus(<number>, <length>); is for columns that need a non-standard width
  • @include grid-column; is for floating columns
    • @include grid-column(<number>); is a shortcut, the same as calling grid(<number>) and grid-column consecutively
    • @include grid-column-empty(<number>, <position>); adds margin to create empty space either before or after the column
  • @include grid-row; is a column container
  • @include grid-page; is the main page wrapper with a full width and is horizontally centered
    • @include grid-page(<number>); creates a page container that is less than the default page width; useful for modal pop-ups

Basic Example Using SASS

Using the ID's and class names already in the markup, it's possible to utilize the mixins that were created earlier to achieve the exact same effect. I typically do this in a layout file that contains all of the column layouts for the various templates in the site.

layout.scssGist page
// establishes page width and centers
#container {
@include grid-page;
}
// main page sections
#container > header, #main, #container > footer {
@include grid-row(true); //true indicates a row is directly inside a page
}
#left-column, #right-column {
@include grid-column(3); //3 columns wide
}
#main-column {
@include grid-column(9); //9 columns wide
// sections in the main column are rows
> section {
@include grid-row;
}
}
#content {
@include grid-column(6); //6 columns wide
}

To Be Clear

  • #container is specified as a grid-page
  • header , #main and footer are set up as grid-row(true)
    • This essentially applies .clearfix to those container
    • grid-row(true) is used for rows contained directly within a grid-page which ommits the negative margins that would otherwise be applied.
  • #left-column and #right column are specified as 3-columns wide
  • The #main-column is 9 columns wide. More importantly, all section tags are specified as grid-row , allowing them to contain columns.
  • The #content column is 6 columns wide.

From the above example it should be clear how to use mixins to apply the grid styles directly through CSS without needing to hard-code the grid related class names into the markup.

Compiled to CSS

Because SASS must be compiled to CSS for it to work in a browser, it's useful to see what CSS is being generated. The file below is what the layout.scss example file generated.

layout.cssGist page
#container { width: 960px; margin: 0 auto; }
#container > header, #main, #container > footer { width: auto; margin: 0 0; }
#left-column, #right-column { margin: 0 10px; float: left; width: 220px; }
.ie6 #left-column, .ie6 #right-column { display: inline; }
#main-column { margin: 0 10px; float: left; width: 700px; }
.ie6 #main-column { display: inline; }
#main-column > section { width: auto; margin: 0 -10px; }
#content { margin: 0 10px; float: left; width: 460px; }
.ie6 #content { display: inline; }
.clearfix, .page, .row, #container, #container > header, #main, #container > footer, #main > section { *zoom: 1; }
.clearfix:after, .page:after, .row:after, #container:after, #container > header:after, #main:after, #container > footer:after, #main > section:after { content: "\0020"; display: block; height: 0; clear: both; overflow: hidden; visibility: hidden; }

HTML Without the Hard-coded Class Names

grid-layout.htmlGist page
...
<div id="container">
<header>
<h1>Header</h1>
<nav></nav>
</header>
<div id="main">
<div id="left-column">Left Column</div>
<div id="main-column">
<section class="hero">
Hero Space
</section>
<section>
<article id="content">Actual Content</article>
<aside id="right-column">Right Column</aside>
</section>
</div>
</div>
<footer>
<p>&copy; Copyright 2010</p>
</footer>
</div>
...

SASS makes it possible to clean up the HTML and remove the extra classes.

Comments