How To Build A Tiny Grid System with Stylus

Saturday, June 16th 2018, 3:57:17 pm

Background

Since I moved my site/blog/etc over to this static, micro-site a while back, I haven’t given it much ❤️ codewise. There are a lot of little visual issues, etc. I haven’t had time to fix in my personal site that I spend all day fixing during my day job. Part of the issue is that I didn’t design the stylesheets very well for this site and they can take time to reason about and edit. In an attempt to change that, I’ve built a micro, responsive grid system here to hopefully make visual updates to this site less painful based on a pretty decent tutorial I found.

How To Build Your Grid System

Variables

So for starters, you need to define a few variables. Think of these as the parameters for your grid system. These parameters are as follows:

// Variables
$GRID_WIDTH = 1200px // How wide is your outer container?
$GUTTER_WIDTH = 20px // How wide are your spaces between cells?
$MAX_COLS = 12 // How many total columns do you need?

// Breakpoint HashMap
$BREAKPOINTS = {
  xs: 0,
  s: 400,
  m: 600,
  l: 800,
  xl: 1080
}
$GRID_WIDTH

So the first parameter above is your $GRID_WIDTH, which determines how wide your outer container is. Think of this as a bound for how big your row can get from side to side.

$GUTTER_WIDTH

The second parameter above is your $GUTTER_WIDTH. This determines the size of the spaces between each of your cells in the grid. Be careful adjusting this value, as it goes up, the space in your cells can be reduced. Keeping this balanced is important. (NOTE: I’ve opted for the “split” system that distributes this value across both left/right. You can read more about this in the post I linked to above’s “Method 3: Split gutters (Margin)” section.)

$MAX_COLS

The third parameter is your $MAX_COLS or the maximum number of columns your grid will support. This can be tricky to select, since it depends on your overall design. However, I tend to like 12 because it has both 2 and 3 as prime factors. This allows for more subdivision options that don’t require rounding, etc. Taken in conjunction with my $GRID_WIDTH value above, this neatly makes my most atomic cell 100px in size, which is a nice bit to work with.

$BREAKPOINTS

The $BREAKPOINTS mapping helps me abstract out the breakpoints in such a way as to make them trivially configurable later and not have to hard-code numbers elsewhere in my code (only string key names).

Mixins

In order to keep this code DRY and easier to work with, I implemented a few helpful mixins. This also avoids copy-pasting very similar code all over the place. That being said, you have to be careful not to over-abstract too early and so I kept the mixins to a minimum of 2:

clearfixer()
clearfixer()
  &:after
    display table
    clear both
    content ''

The clearfixer() mixin generates the pseudo-selector after element that vertically pushes down each cell in a row. Since they are floating, this is required. Perhaps in a subsequent iteration I might try to use a different type of system that avoids this, but for now it’s simple and more widely supported than alternatives.

columnProperties(n, gutterWidth)
columnProperties(n, gutterWidth)
  w = unit(gutterWidth * n, px)
  width "calc(calc(100% - %s) / %s)" % (w n)
  margin-right (gutterWidth / 2)
  margin-left (gutterWidth / 2)
  float left

The columnProperties(n, gutterWidth) mixin generates the rules for each .k-c-{n} and .k-c-{n}-{bk} class. This allows me to define it in one place and easily scale it out to many breakpoints, etc. In a sense, this defines the meat of each column’s class and makes the necessary calculations based on my input variables. I’ve also parameterized them into this mixin to keep it somewhat flexible and usable in any context later.

CSS Rules and Classes

So for starters, a few global properties will need to be used in order to make sure our box-sizing is universally what we expect. For the reasoning behind this, I recommend reading about box-sizing elsewhere.. It’s a bit out of scope here.

html
  box-sizing border-box

  *,
  *:before,
  *:after
    box-sizing inherit

Afterwards, a utility class can be setup to define the row container. I recommend adding a pseudo-vendor prefix. I used k-* to help me distinguish my class names from others brought it via libraries and implement a micro-name-space:

.k-row
  max-width $GRID_WIDTH
  margin-left auto
  margin-right auto
  clearfixer()

Finally, you are ready to define your .*-col classes:

.k-col
  // Make standard column defs
  for n in (1..$MAX_COLS)
    &.k-c-{n}
      columnProperties(n, $GUTTER_WIDTH)
  // Make breakpoint specific column defs
  for bk, val in $BREAKPOINTS
    for n in (1..$MAX_COLS)
      @media (min-width: unit(val, px))
        &.k-c-{n}-{bk}
          columnProperties(n, $GUTTER_WIDTH)

In the end, this will generate your tiny, highly configurable grid system in ~50 lines of stylus:

Here it is altogether:

// --- Variables ---
$GRID_WIDTH = 1200px
$GUTTER_WIDTH = 20px
$MAX_COLS = 12

// For now only two breakpoints are fine
$BREAKPOINTS = {
  xs: 0,
  s: 400,
  m: 600,
  l: 800,
  xl: 1080
}

// --- Mixins ---
// Generates a clearfix for the rows
clearfixer()
  &:after
    display table
    clear both
    content ''

// Applies the column properties
columnProperties(n,gutterWidth)
  w = unit(gutterWidth * n, px)
  width "calc(calc(100% - %s) / %s)" % (w n)
  margin-right (gutterWidth / 2)
  margin-left (gutterWidth / 2)
  float left

// --- Global Rules ---
html
  box-sizing border-box

*,
*:before,
*:after
  box-sizing inherit

.k-row,
.k-wrap
  max-width $GRID_WIDTH
  margin-left auto
  margin-right auto
  clearfixer()

.k-col
  // Make standard column defs
  for n in (1..$MAX_COLS)
    &.k-c-{n}
      columnProperties(n, $GUTTER_WIDTH)
  // Make breakpoint specific column defs
  for bk, val in $BREAKPOINTS
    for n in (1..$MAX_COLS)
      @media (min-width: unit(val, px))
        &.k-c-{n}-{bk}
          columnProperties(n, $GUTTER_WIDTH)

For examples on how to use this, you can check out the source code for this site’s grid.styl on Github or this Codepen I made using this grid system:


Omar Delarosa avatar

Written by Omar Delarosa who lives in Brooklyn and builds things using computers.

Add me on LinedInFollow me on GithubFollow me on TumblrFollow me on Twitter