Sass and Bourbon Neat for Lightweight Semantic Grids

Tweet

If you’re already a fan of Sass and Bourbon, you’re going to love Neat – a lightweight, semantic grid system that works seamlessly with Bourbon and Sass, from the same folks at Thoughtbot who wrote Bourbon.

In case all this sounds new to you, Sass is a preprocessor for CSS that can help improve your CSS workflow tremendously. Bourbon is a set of mixins for Sass that enhances and extends Sass’s power. If you’re not familiar with Sass and Bourbon check out my previous article describing how to get set up with Sass and Bourbon in a few simple steps. Once you’ve gone through that, you should be ready to follow along and learn all about Neat.

Modular Approach

One of the objectives of the Bourbon framework is to keep things modular, so you don’t end up cluttering your code with features you don’t actually use. With this in mind, the makers of Bourbon released their Neat grid system as an optional add-on for Bourbon. They wanted a small and semantic grid system that could help with the majority of common layout tasks without being too opinionated.

The goal was to make something that you could take advantage of when you wanted it, and that would get out of your way when you didn’t. Neat can be included in a Bourbon project if you want it, but unless you make use of it, it won’t add anything to the compiled CSS you will end up serving to your visitors.

What is a Semantic Grid?

Semantic is a term that gets thrown around a lot in web development. For the purposes of Neat, what makes this grid system semantic is that it allows you to target your HTML elements based on the way they are named natively, and use them as they were intended to behave, keeping your markup clean.

A quick example might help.

Imagine you’re building a page that needs to display an article with an aside inside a section. You want to use the correct HTML elements, and you don’t want to have to clutter the page up with unnecessary classes or wrappers. You want the aside to stay positioned to the left of the article on a typical desktop display. You know you’ll want the flexibility to present the same elements in different ways on different devices as well.

You start with some simple HTML:

<section>
  <aside>
    <p>Highlighted information</p>
  </aside>
  <article>
    <p>This is the content of the article</p>
  </article>
</section>

Without any CSS, this is going to put the aside content at the top, followed immediately by the article. To make the presentation use a grid layout, you need to target the appropriate elements with Neat’s grid classes. You define the section element as a container, and then establish the number of columns (out of 12 by default) to allocate for its children (the aside and the article).

@import bourbon/bourbon
@import neat/neat

section {
  @include outer-container;
  aside {
    @include span-columns(3);
  }
  article {
    @include span-columns(9);
  }
}

This all works seamlessly with any of your usual Sass and Bourbon conventions, and all the classes and CSS selectors you might prefer to use. So if you want to make this happen only for section elements that have a particular class, Neat does its job and gets out of your way. So for the following HTML:

<section class="article-container">
  <aside class="interesting-insight">
    <p>Highlighted information</p>
  </aside>
  <article class="syndicated-content">
    <p>This is the content of the article</p>
  </article>
</section>

This Neat definition will work just the way you would expect it to (we’ll assume the import lines at the top of the Sass file going forward):

.article-container {
  @include outer-container;
  .interesting-insight {
    @include span-columns(3);
  }
  .syndicated-content {
    @include span-columns(9);
  }
}

Responsive Layouts

The resulting page from the above examples will show the aside content to the left of the article content, no matter how big or small the window gets. But suppose you want the aside to pop up to the top when the device display is 500px or narrower.

You can make that happen by defining a $mobile breakpoint variable at 500px with Neat’s new-breakpoint() function. This even allows you to specify the number of columns that should represent the entire width of the new screen size for all elements in this context:

$mobile: new-breakpoint(max-width 500px 4);

section {
  @include outer-container;
  aside {
    @include span-columns(3);
    @include media($mobile) {
      @include span-columns(4);
    }
  }
  article {
    @include span-columns(9);
    @include media($mobile) {
      @include span-columns(4);
    }
  }
}

Now the aside and the article will be stacked, and set to a full four-column width to fill the screen horizontally if the display is 500px or narrower. And on larger displays, the visitor will get the same side-by-side presentation as before.

So let’s take a look at the CSS that gets generated when this basic responsive example is compiled:

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

section {
  max-width: 68em;
  margin-left: auto;
  margin-right: auto;
}

section:after {
  content: "";
  display: table;
  clear: both;
}

section aside {
  float: left;
  display: block;
  margin-right: 2.35765%;
  width: 23.23176%;
}

section aside:last-child {
  margin-right: 0;
}

@media screen and (max-width: 500px) {
  section aside {
    float: left;
    display: block;
    margin-right: 7.42297%;
    width: 100%;
  }

  section aside:last-child {
    margin-right: 0;
  }
}

section article {
  float: left;
  display: block;
  margin-right: 2.35765%;
  width: 74.41059%;
}

section article:last-child {
  margin-right: 0;
}

@media screen and (max-width: 500px) {
  section article {
    float: left;
    display: block;
    margin-right: 7.42297%;
    width: 100%;
  }

  section article:last-child {
    margin-right: 0;
  }
}

There are a lot of best practices and CSS tricks in there to make the resulting styles robust. For example, Bourbon and Neat took care of clearing the sections, setting table display styles for the container and child element, making sure last-child elements don’t have right margins, and even calculating percentage-based widths and margins to five decimal places for both small and large displays on the aside and article elements. That’s a lot of value for the amount of effort involved.

Content Priority Ordering

If you want to switch the order of display for elements in a particular view without changing the order of the content in your HTML, Neat supports convenient and intuitive negative row positioning. You can shift each column around inside its parent element as easily as this:

section {
  @include outer-container;
  aside {
    @include span-columns(3);
    @include shift(-12);
  }
  article {
    @include span-columns(9);
    @include shift(3);
  }
}

Now the article element will be on the left, and the aside will be on the right. And you can add back the mobile styles the same way as we had them before to keep your responsive display consistent:

$mobile: new-breakpoint(max-width 500px 4);

section {
  @include outer-container;
  aside {
    @include span-columns(3);
    @include shift(-12);
    @include media($mobile) {
      @include span-columns(4);
    }
  }
  article {
    @include span-columns(9);
    @include shift(3);
    @include media($mobile) {
      @include span-columns(4);
    }
  }
}

Customizing Settings

One of the real advantages of Neat is that it’s very flexible about how it can be configured using built-in settings. Neat allows you to pass your own values for the majority of customizations you might want to set while developing your site, and also allows you to use practical and reasonable defaults for values such as column counts and gutter widths.

Neat assumes a 12-column grid by default, which is flexible enough for a wide range of layouts, but you can use a 16-column grid if it’s more convenient just by changing the value of the $grid-columns variable.

$grid-columns: 16;

section {
  @include outer-container;
  aside {
    @include span-columns(4);
  }
  article {
    @include span-columns(12);
  }
}

Nested Sub-Sections

Neat also allows sub-grids within containers in a layout. This can support flexible presentations that show multiple side-by-side elements positioned cleanly inside a nested element. All you need to do is specify that the columns for the interior elements should be calculated based on the number of columns occupied by the nested parent element.

For example, here is an article with three nested div elements:

<section>
  <aside>
    <p>Highlighted information</p>
  </aside>
  <article>
    <div>This is the first sub-nested element</div>
    <div>This is the second sub-nested element</div>
    <div>This is the third sub-nested element</div>
  </article>
</section>

In such a case, you can specify in your Neat Sass code that each one should take up a share of the available columns inside the containing element:

section {
  @include outer-container;
  aside {
    @include span-columns(3);
  }
  article {
    @include span-columns(9);
    div {
      @include span-columns(3 of 9);
    }
  }
}

And because Bourbon and Neat are just enhancements to Sass, they’re fully modifiable using standard Sass development techniques.

Customizable and Unobtrusive

Neat is versatile enough and simple enough to support most standard approaches to layout development. If you want to do mobile-first layout with a single column that expands to two columns on a tablet and three columns on a desktop, or if you want to eliminate the spacing between columns, or support multiple rows of items within a single set of sibling elements, Neat has you covered.

Check out the Neat documentation and browse through some of the examples on the Neat site to get inspiration for your next project. With Bourbon and Neat on top of your Sass, you can dive in and start playing with design and layout options right away, knowing that you’re not adding a lot of extra bloat to your code, or cramping your semantic HTML style.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Anthony Candaele

    Thanks for this article David. Much appreciated, as there are not so much tutorials on how to use Bourbon Neat. I also use Bitters in my projects because it has some sensible defaults and you get a head start without bothering with the plumming code.

  • Aaron Betts

    Excellent tutorial. Thanks!

  • Lars Faye

    I completely misunderstood the Shift function and didn’t realize I could use it to change the order of elements in terms of the grid collapse (e.g. Sidebar/Content on Desktop but Content/Sidebar on Mobile). Oh my, this is awesome. THANK YOU.