You must be so tired of reading about grid systems

I’ll start off this brand new blog of mine by talking about something that’s occupied my mind for the last few months. Yeah, grid systems.

Most front end developers have been wading through the muddled waters of .col-5’s and .span9’s by now, often to find every solution a bit lacking in real life situations.

We need a solution that caters to the other current buzzword: Adaptive design. We’re instructed to use these seemingly handy helper classes to define our column widths. But what happens when a .span9 needs to turn into a .span6.offset2 on a tablet in portrait orientation? So we learn to change our methods, unless we explicitly know the widths will never change. We tirelessly crawl through our media queries and change widths like nobody’s business. Don’t you wish it was easier? I sure did. I’ll tell you how I made a solution that’s perfect for me.

Get to it, already…

I prefer a grid system that adds and subtracts columns depending on the width of the viewport. I don’t want to be stuck in a 16 column grid layout for every possible width. So I got excited when I happened upon Joni Korpi’s Frameless Grid. Finally a way of thinking that I can get behind.

Basing my thought process on this idea I started working on a solution that would be flexible enough for me to be happy with and simple enough for me to not become bored or annoyed with. I do both design and development on a lot of my projects, so I wanted a solution that helped me change things around quickly and without fuss. The result is a handy SASSified set of functions and mixins that enables me to just write @include width(4) to get a rem-based 4 column width with px fallback for old and busted browsers. Now this sounds very similar to the solution Frameless Grid proposes, but I like to think I’ve modernized and improved the technique a little.

Toggle page grid

Before I go on to post example code and talk more about the hows and whats, press the button or hit ctrl+g to see this page’s grid setup (Mozilla and Webkit only). Unless I messed up, everything should line up with both the grid columns and the baseline grid. As a man with a background in print design, this pleases me immensely. It feels like finally having found the Holy Grail of front end web development.

Wait, was the wheel just reinvented?

I realize this is not entirely new. Blueprint CSS‘s solution is quite similar, and as I mentioned the grid columns are based on Frameless Grid. Joni Korpi also made the Golden Grid System, which uses a really nice baseline grid. I’m sure there are plenty of other solid solutions out there, but none of them were really for me. If it doesn’t feel right, it probably isn’t worth using.

My solution is still in development, as it has some growing pains. I’m still working on finding the best solutions for these problems.

So how was it done?

Well, after scouring the internet for solutions to satisfy my obsessive desire to make everything line up, I gathered the best ideas and started writing up the CSS. It quickly became apparent that I would benefit from making use of my nemesis, SASS. Previous to this endeavor I was ambivalent about using any CSS preprocessor at all, but making all my calculations in functions and mixins made the most sense in this case.

SASS lets me set up a group of predefined variables that defines the entire layout (The setup is borrowed from Frameless Grid, and I ain’t the slightest bit ashamed about that). Let’s say you want to use the browser’s base font size (16px in every major browser), with a double line height. You’ve decided the perfect column width is 50px (don’t worry, I only use absolute pixel sizes as fallback for old browsers), with 25px gutters. Your base variables would be:

$font-size: 16;
$line-height: $font-size * 2;
$column-width: 50;
$gutter-width: 25;
$rem: $font-size / 1rem; // We'll use this to convert px to rem

If you’re not familiar with rem sizes, you should read Jonathan Snook’s article about sizing with rem. If you read through that you’ll see why I’ve decided to include px fallbacks for all rem sizes. Here’s an example of the mixins I use for font sizes and line heights, with fallbacks for crappy browsers:

@mixin font-size($size: $font-size) { 
  font-size: $size + px; font-size: $size / $rem; }
@mixin line-height($line: $line-height) { 
  line-height: $line + px; line-height: $line / $rem; }

If you’re not sure what I’m doing here, read the tutorial on SASS’ website.

From here on it gets a tiny bit math’y. Basic concept is still from the previously mentioned source, with adjustments.

// Mixin for returning pixel and rem values
@mixin rem($property, $pixel) { 
  #{$property}: $pixel * 1px; #{$property}: $pixel / $rem; }
// Function to calculate the width of an element
@function calcwidth($cols) { 
  @return ($cols * ($column-width + $gutter-width) - $gutter-width); }
// Mixin to include width in px and rem
@mixin width ($cols:1) { 
  @include rem(width, calcwidth($cols)); }
// Mixin for "rows", or anything spanning the entire width
@mixin fullwidth($cols:8) { 
  @include rem(width, $cols * ($column-width + $gutter-width)); }

That’s it, that’s all I need to start putting my widths into the elements. From here on I just needed to make sure the columns behave like they should. There are a few ways I could have done that but I opted for adding a class .column to all the elements I need to behave like a floated grid element, and a class .row to my full width elements, simply because I didn’t want to do this:

.col {
  float: left;
  display: block;
  position: relative;
  @include rem(margin-left,$gutter-width);
.site-footer-row {
  display: block;
  margin: 0 auto;
  @include fullwidth();

When I instead could do this:

.column {
  float: left;
  display: block;
  position: relative;
  @include rem(margin-left,$gutter-width);
.row {
  display: block;
  margin: 0 auto;
  @include fullwidth();

I’m not adverse to adding .column classes in my HTML. When marking up the HTML I’ll know which elements will be floated grid elements so it’s all the same to my work load if I do it one way or the other. In certain cases I can see how it would be beneficial to do it in CSS though.

Now what?

Now we style! For this blog I started my styling from a 16 column layout, because it simply saved me time, but ideally I’d start from 8 columns, so older browsers that doesn’t support media queries (Read: Internet Explorer below 9) would get a decent fallback. My target audience doesn’t really include people who use old browsers, so I could allow myself this freedom. The only caveat of this is that I can’t serve low-weight content to small screens through CSS. I can live with that on my personal blog.

Let’s look at how I’ve laid out the article content you’re currently looking at, and how I ensure no columns are ever too wide for the viewable area.

// <div class="art-content column">
.art-content { @include width(8); }
@media screen and (min-width: 12.5em) { // safe and low number (200px)
  // columns shouldn't be wider than 4 columns at this size
  .column { @include rem(max-width,calcwidth(4)); }
@media screen and (min-width: 40em) { // 640px / 8 columns
  .column { @include rem(max-width,calcwidth(8)); }
@media screen and (min-width: 60em) { // 960px / 12 columns
  .column { @include rem(max-width,calcwidth(12)); }
@media screen and (min-width: 80em) { // 1280px / 16 columns
  .column { @include rem(max-width,calcwidth(16)); }

That’s the entire premise of the system. In addition, I bump up the rem, root font-size, on breakpoints of appr. 1600px and 2000px, so users with higher resolution or very big monitors will get an overall size increase. I use both min-widths and max-widths in my stylesheets to control how elements get laid out in the different column counts, but if you plan your site right there really should be very little to do outside of minor adjustments and the .column { max-width } in media queries.

I’m currently testing out this concept on a massive website in production. We’ll see if it improves my workflow. I’ll more than likely document parts of my process on this here blog right here. Keep coming back!

And thus concludes this first installment of Jan Schjetne bores everyone to death. I hope you’ll be coming back for more long winded posts about CSS and otherwise. Please tweet at me if you have any comments or feedback on this article.

Comments? Tweet me!