Using Bourbon Neat for CSS Grid Structure with Semantic Markup


Semantic markup makes me happy.

Bourbon Neat gives me a way to use a grid structure on my web page AND be happy. When we look at the most widely adopted grid systems — such as Bootstrap, Foundation, 960 Grid System, Skeleton — there is an inherent problem with the standard way it’s used.

The Problem: Presentation Classes

Each of these systems involve applying classes to elements in your markup that look something like this:

<section id=”content” class=”row”>
<article class=”small-12 medium-10 large-8 columns”>
<h1>…</h1>
<p>…</p>
</article>
<aside class=”small-12 medium-2 large-4 columns”>…</aside>
</section>

This means that if I want to adjust how the content is displayed, I have to change my markup.

Keeping things where they belong

When your HTML is describing how something looks. Something is broken.

The Content Layer:
Your content should be able to be understood independent of the rules on how it looks. This ends up being rendered as HTML, but could start in a number of different forms (JSON, XML, markdown, etc).

The Presentation Layer:
It’s hard to talk about the separation of content and presentation without going back to the CSS Zen Garden. It’s a beautiful demonstration of CSS’s role in providing a home for presentation, while the content resides in the markup.

Behavior Layer:
This is where stuff happens based on events. Generally speaking, this is JavaScript’s home.

By maintaining these lines of separation, you’re positioning yourself for a better workflow in which someone responsible for the layout or style of the content of the page only needs to work in the CSS of the project. If you were able to apply these column spans from your grid system to your elements in the project’s CSS rather the HTML, you elimate the need for these darn presentation classes.

It could look something like this:

<section id=”content”>
<article>
<h1>…</h1>
<p>…</p>
</article>
<aside>…</aside>
</section>

Ahhhh. Now doesn’t that feel nice? Our markup is semantically telling us about our content and nothing more. So, how do we get the same effect of a grid system without junking up our HTML? That’s where Bourbon Neat comes in.

What is Bourbon Neat?

Neat is a set of SASS mixins that build on top of Bourbon, which builds on top of SASS. It gives us the ability to apply those column spans in your SASS, to then be outputted into your compiled CSS. Thus, giving you the end result of a functioning grid system while keeping our HTML nice and tidy.



Here’s what that would look like (based on a standard 12 column grid):

#content {
@include outer-container;

article {
@include span-columns(8);

@include media($medium-screen) {
@include span-columns(10);
}
@include media($small-screen) {
@include span-columns(12);
}
   }
aside {
@include span-columns(4);
      @include media($medium-screen) {
@include span-columns(2);
}
@include media($small-screen) {
@include span-columns(12);
}

}
}

This is a nice place to start, but Neat actually offers some additional control that is pretty…well…neat.

The Grid Settings (_grid_settings.scss)

Using Neat, you can change the number of columns in your grid at each breakpoint.

Grid Settings to define breakpoints

Let’s breakdown what’s happening here. If we look at the $small-screen line, you’ll see some simple math happening $first-breakpoint (defined above as 400px) – 1 = 399px which is then converted to ems. Then, the number at the end of the line defines the number of columns in the grid at that breakpoint. If that number is blank, the default number of $grid-columns is applied.

The reason for the math here is used here is to scaffold the media queries rather than cascading them over each other. This will come in handy when getting into the omega mixin.

If I want to set up a group of content — let’s say an image gallery — where I want each image to take up 1/4 of the page on the desktop. I’ll write it like this:

.gallery .item {
@include span-columns(3);
@include omega(4n);
}

In this case, each ‘.item’ is going to span 3 of my 12 columns — fitting 4 across. However, without the omega, the margin-right used to establish the gutter would make the 4th-child being too wide for the container, which will result in that object getting bumped down below.

What Omega Does

.gallery .item:nth-child(4n) { margin-right: 0; }
.gallery .item:nth-child(4n+1) { clear: left; }

Using Media Queries with Omega

Because the media queries set up above do not overlap, we avoid running into having omega(1n) AND omega(2n) AND omega(4n) being applied to the content simultaneously.

Extending to Make it more DRY

Web content frequently takes up a general proportion of the page width based on the size of the screen. For example: one-third on a desktop, then 100% on tablets and phones. We can turn each common distribution of space into their own mixin.

I’ve put together the following mixins.

This gives me a reusable way to handle a block of content responsively with a single line of SASS.

.gallery .item { @include one-quarter; }

The -nom suffix is a convention for “no omega”. Leaving omega out in this case, makes them a little more versatile in situations such as a one-third/two-thirds distribution. Leaving the omega out of the mixin allows you to put the sidebar(one-third) on either side. Then add the omega to the object.

#content {
@include outer-container;

article {
@include two-thirds-nom;
}
aside {
@include one-third-nom;
@include omega;
}
}

Added Bonuses

Partial Columns: By using SASS for my column-spans, you can use partial columns for you widths. For example: two-thirds of an 8 column grid would be @include span-columns(5.33);

Visual Grid: In the grid settings file, you can set $visual-grid to true to see an overlay of the grid on top or below your content. This is helpful with debugging what’s going on if things are lining up correctly. You can even adjust the color and opacity.

Visual Grid

There are a number of other grid systems taking on this same type of practice. Susy is quite comparable. Some people are doing the same thing with Bootstrap using LESS and .make-lg-columns(3); ZURB even has a document covering this. This is just the solution that I’ve adopted and it’s working quite beautifully. Let me know what you find works for you.

Additional Resources

How to make your CSS awesome with Bourbon, Neat, Bitters and Refills!

https://www.youtube.com/watch?v=EDP-iUd5ZPI