Sass Grids: From Neat To Susy

By James Steinbach

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 {
  // 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.


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.

  • Jitendra Vyas

    At the end what do you mean by “while giving you the freedom to write classes in your HTML markup however you deem best”

    • James Steinbach

      I mean that you’re able to use whatever HTML class names you (and your organization) prefer. Some devs prefer content-descriptive classes like .post-content, .sidebar, or .site-header; others prefer more layout-focussed classes like .wide-column, .narrow-column, or .full-width. With Susy, that preference doesn’t matter: you can use any class names, then use Susy mixins to give those classes the right grid-layout styles.

      This is a big benefit in contrast to many CSS grid stylesheets that require you to use their classes (.col-sm-9, etc) to control layout.

  • Todd Zmijewski

    Ever since I discovered susy working with the Drupal omega theme I’ve loved it. Every chance I get to use sass susy is a much welcomed addition to my workflow. Coupled with breakpoint it is one powerful set of tools. I believe it is far superior to any CSS grid system like 960, bootstrap, etc.

  • Antonio

    The problem with the latest release of Susy and singularitygs is they aren’t supported by libsass. Sass is way slow and the only solution to have a quick live reload/compilation while working with large projects is to use libsass. It’s faster than other frameworks/preprocessors. I use it with bourbon and neat but although I don’t mind about missing compass, often I feel the need of a more robust grid system like Susy or singularitygs.

    • Stuart Robson

      The good news is the developers behind Sass and libSass have recently announced that they will start to update both versions when there is feature parity. In the interim Eric M. Suzanne has developed and released Su: a DIY grid system using the Susy engine which might be worth a look.

      • Mike

        Eric released Susy 2.2.1… Susy now works with LibSass.

  • Ricardo

    Hello James,

    Thanks for this article. I was using Neat but it seems like Susy earned a opportunity with me. However I wanted to ask the following: are grids still necessary when Flexbox is out there and pretty well supported? I’m doing a personal project from scratch, no framework or something else than SASS and I’ve found Flexbox so versatile that I think I’m not needing a grid anymore. Any comments about it?


  • StNick

    Hi James,
    I have to say I’m starting to like Susy! I was wondering, if I wanted to use Susy together with Bourbon and Bitters, would I just have to import susy instead of neat in my app.sass? Or would there be more work required to let the two systems work together properly?

    • Supervan

      Hi StNick,
      Did you have any conflicts with this combination..

      • StNick

        Haven’t had the time yet. I’ve decided to continue my projects with Bourbon&Neat.

        • James Steinbach

          I’ve used Susy alongside Bourbon & Bitters before – no conflicts. In fact, since the functions/mixins/variables are all named differently, you should be able to safely use Susy alongside Neat without Sass conflicts. (Though I’m not sure that’d be a good idea long-term!)

  • Nilesh Prajapati

    Great article and I recently reconsider my workflow switching from neat to susy and now knowing that susy no longer required compass by default which was a turn off for me and can be run on it own. As great the article made me consider switch I do feel that the articles required images to show the example but also I been using bourbon for a while and I do enjoy bourbon implementation, documentation and certain functionality like rem functionality and more but I would like know how did you setup your susy file being not familiar with susy development which did confuse I’m in this article.

  • Paweł Grzybek

    Sussy is amazing tool. My approach is way simpler cause to learn Sussy is quite lonf learning curve. I designed something way simpler and works fine for me all the time, have a look

  • Andrew McSwain

    Great Article James. This kind of content for susy is in limited
    supply. I appreciate the effort. After searching for a good 20 minutes
    for information concerning “with-layout” I came across your article.

    the mixin @with-layout is not being recognized at all in Sassmeister. I
    tried adding it to the container div within which rests my CTA divs–
    no luck.

    Copy and pasted from your example: “CSS not recognized”

    Am I missing something here?

    there some differences between the other mixins like, @include @extend
    span() container() ? Each of these has functioned (almost) flawlessly
    for me, now @with-layout is not even being recognized.

  • Christian Goodrich

    Hi James, really useful insights and comparisons, thank you. So I’m clear, does Susy not have a $gutter variable like what Neat does? I’m wanting to add some vertical padding to one of my grids.

    • Christian Goodrich

      Hi James, might have just answered my own question – with Neat the variable is $gutter, whereas with Suzy it is just gutter()

  • Christian Goodrich

    Hi James. You mention about gallery() mixin being your favourite, and you note how it works well with breakpoints. But what if you want to specify @include gallery(12 of 12)? This seems to create an issue for me, and stacks all the elements on top of one another! Appending clear: both !important; fixes the issue, but surely this isn’t the best approach. Is there a better workaround that you’re aware of?

    • James Steinbach

      I’m not sure what the use case for `gallery(12 of 12)` would be :)

      Since that *should* just make all the element 100% wide, you wouldn’t need any Susy math at all, just `display: block` on all those elements.

    • James Steinbach

      I’m not sure what the use case for `gallery(12 of 12)` would be :)

      Since that *should* just make all the element 100% wide, you wouldn’t need any Susy math at all, just `display: block` on all those elements.

  • Jhanwarlal Kumawat

    Can column-count css3 properties same as row-count css3 property?

  • Jhanwarlal Kumawat

    Can column-count css3 properties same as row-count css3 property?

  • Jhanwarlal Kumawat

    Can column-count css3 properties same as row-count css3 property?

  • Rafael Guedez

    In my case I moved from Susy to Neat. I do all the same things with Neat and keeping the compile time in less than 200ms, even in complex sites the perception is real time (using libsass). With Susy each single @include span() increase the compile time.

  • dancinglightning

    nice article, thanks
    i really like susy as it does what the work needs: seperate view from structure. With it’s semantic class names and powerful includes a developer team finally gets the seperation of concerns that css promised (but eg bootstrap takes away again).
    Just waiting for that ecosystem to sprout around it :-)



Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Front-end, once a week, for free.