HTML & CSS - - By James Steinbach

Sass Grids: From Neat To Susy

For the last several months, I’ve been using a Sass grid system called Neat. It’s done almost everything I need and it’s pretty easy to get started with. However, lately I’ve found myself writing extra styles to augment the Neat grid. Rather than extend it on my own, I decided to find a Sass grid system that was more powerful. That system is Susy.

A Grid Framework, Not a Grid System

Before we get into the how to use Susy, let’s talk about the importance of using a Sass grid framework, not a grid system. As I’ve been using Sass grid frameworks for layout, I’ve found 3 main advantages.

First, I can give my markup whatever classes I like. It doesn’t matter if you like BEM, SMACSS, OOCSS, or any other class naming structure: you can use a framework like Susy without changing your markup. On the other hand, grid systems (like Bootstrap, for example) require you to add their class names to your markup.

Second, grid frameworks are more maintainable. You can change column widths and other visual layout styles by changing only some lines of Sass: your settings or a few mixins. But if you try changing your layout with a class-based grid system, you would have to rewrite your markup.

Third, preprocessor grid frameworks are lighter and faster for your users. Used properly, a framework will output only the styles you need for your specific layout choices. A grid system, on the other hand, will include all of the styles for all of the grids at all of the widths, requiring you to do a good bit of pruning if you want to keep your sites nice and lean.

Basic Syntax

Let’s begin by going over the bare minimum you need to know to build a simple Susy based layout. Along the way, I’ll be comparing it to Neat’s syntax for the same output: if you’re also switching from Neat to Susy, this will help you translate the basic concepts over.

Susy Config: $susy Map

All your global settings for Susy are stored in a map called $susy. This makes it easy to keep your config data in one place. If you were going to generate a 12-column grid at 960px with 20px of gutter between each column, you’d use the following map:

$susy: (
  columns: 12,
  gutters: .25,
  container: 960px
);

The gutters value corresponds to a percentage of the full column width. Since 12 columns in a 960px container would be 80px each: therefore, .25 will give us a (rough) 20px gutter.

Note, you can use a fractional gutter value (like 1em/8em) with a column-width value and math: static, but the rounded .25 is probably simpler than all that.

In Neat, you’d use a series of variables for this setup:

$grid-columns: 12;
$max-width: 960px;
$gutter: 20px;

On one hand, Neat’s $gutter variable is more powerful than Susy’s $gutter value: it’ll take a px, em or % value. But on the other hand, all those unscoped variables present a greater risk of Sass plugin conflict. Another “gotcha” on Neat variables is that it’s best to declare them before you import Neat into your primary Sass files.

Creating Containers: container() Mixin

The mixin container() will use the information in $susy and set up a container (clearfix, max-width, & centered) for your grid items. Its use is very straightforward:

.content {
  @include container;
}

Neat does roughly the same thing with the outer-container() and row() mixins. Personally, I prefer having only one mixin to worry about for that: in some cases, row() could encourage extra markup mimicking Bootstrap’s .container > .row > .col pattern where the extra wrapper is unnecessary.

Defining Columns: span() Mixin

To align child elements along the grid, use the span() mixin. This takes 3 parameters in Susy: span, location, layout.

.sidebar {
  @include span(5);
  // width = 5 columns of $susy: ( columns ) value
}
.sidebar {
  @include span(5 of 12);
  // width = 5/12 with margin specified by $susy: ( gutter )
}
.sidebar {
  @include span(5 at 8 of 12);
  // width = 5/12 with margin removed from right
  // because 5 col starting at 8 = last column
}

The location parameter can also be written with keywords first and last:

.sidebar {
  @include span(5 last);
}

In Neat, I used the span-columns() mixin. It took some different parameters: column-count (with optional context-column-count) and display (allows you to set block / table-cell layout).

Advanced Features

Now that we have looked at the basics of setting up a grid with config options in $susy, a container(), and several children with span(), let’s look at some of the more powerful things Susy can do easily.

Changing Layouts: with-layout() Mixin

What if you need to set a different column count on different pages? Susy makes that easy with the with-layout() mixin. This allows you to temporarily override your global $susy config for a single block of code. (Think of it like scoping a variable.)

.different-column-count {
  @with-layout(10);
  // deviates from the global 12 columns
  // & calculates span() based on 10
}

Neat doesn’t have an equivalent to this: you’d need to explicitly include the new column count for each child: @include span-columns(X of 10).

Changing Output: output: isolate Setting

Browsers aren’t the best at math. I know, they’re just computer programs: they should be perfect. But they round percentages to the nearest pixel, and in some cases that can prevent precise grid alignment. Susy supports a CSS floating technique called “isolate” that fixes that with some fancy negative margin magic. Just include output: isolate in your $susy settings. This may not be necessary all the time, but if you’re unhappy with some browser rounding choices, this will probably smooth things out for you.

Neat doesn’t provide this output option, but it does allow CSS table based grid output.

Justifying Columns: last-flow: to Setting

Sometimes you need a grid layout where the total child columns is less than the grid column count and you want a gap in the middle. In other words, you want :last-child to float to the right instead of resting next to its neighbor on the left. There’s a $susy setting for this as well: last-flow: to.

Neat doesn’t have this feature: you’d need to write plain CSS for this:

.container {
  :last-child {
    float: right;
  }
}

Getting Column-Width: span() Function

You may need to use the column width in another part of your CSS besides the grid layout. Susy provides a function called span() for this (don’t confuse it with the mixin span(), though!). For example, you may want all your inline images to be 4/12 columns wide, but you’re not floating them on a grid:

.container img {
  width: span(4 of 12);
  height: auto;
}

If Neat had this function, it might be a toss-up, but this puts Susy way ahead.

Getting Gutter Width: gutter() Function

This works the same as the span() function above, but gutter() returns the gutter width being used by the grid. You might use this if you’re doing some vertical alignment and want that to match your grid gutters:

.article-title {
  margin-bottom: gutter();
}

In Neat, you could get this measurement just by calling the $gutter variable.

Real Grids: gallery() Mixin

This is one of my favorite Susy mixins. Most grid layouts just do a few columns inside a clearfix container. What if you want to have several rows of actual grid content in a single container? Susy gives you the powerful gallery() mixin. This takes care of those pesky :last-child margin fixes for you. (You could do this manually with the CSS :nth-child(#{$grid-count}n) { margin-right: 0 }, but why not let Susy do it for you?)

.gallery-item {
   @include gallery(3 of 12);
}

Neat has the omega(#{$grid-count}n) mixin to accomplish this layout. I’d rather use a single mixin and save myself some time, though. Susy’s gallery() mixin does a much cleaner job changing widths across breakpoints:

.grid-item {
  @include gallery(6);
  @media (min-width: 600px) {
    @include gallery(4);
  }
  @media (min-width: 800px) {
    @include gallery(3);
  }
}

Responsive Grids

You may have noticed that I used vanilla CSS media queries (Sass nesting, but still, just media queries) for breakpoints. Susy doesn’t come with a full built-in breakpoint manager; the developers behind it recommend using Breakpoint and provide susy-breakpoint() a helper mixin that calls Breakpoint:

@include susy-breakpoint(720px, 8) {
  // At a min-width of 720px, Susy will use a 8-col grid
  .responsive-grid-item {
    @include span(4);
  }
}

Neat has a set of breakpoint helper functions & mixins, but I’ve never used them. I use my own breakpoint mixin and have never had a need for Neat’s tools.

Conclusion

Managing your grid and column layouts with Sass is a great way to streamline development, simplify maintenance, and launch faster sites. Susy provides a powerful toolkit for defining and using various grid layouts, while giving you the freedom to write classes in your HTML markup however you deem best.

Sponsors
Login or Create Account to Comment
Login Create Account