Understanding Neat 2.0 Grids

We’re big fans of the Bourbon set of Sass tools here at Highrise Digital, with its Neat component being our go-to grid system.  But starting out with any new technology often involves a bit of a learning curve, so if you’re new to Neat grids hopefully this guide will help you.


I’ll assume you’ve already got Bourbon and Neat installed in your project and are at the point of putting the HTML and Sass together.  If you need installation instructions head over to the Neat homepage.

Code examples are based on Neat 2.x, with 2.1.0 the latest version at the time of writing.

Neat vs other grid frameworks

As Neat is a Sass-based grid, the most obvious difference compared to other grid systems like Bootstrap and 960 Grid System is the lack of presentation classes in your HTML markup, and by presentation classes I mean the “col-xs-12 col-md-8” classes scattered across HTML elements:

Whilst I’ve found this approach handy when designing in the browser, mixing the Presentation and Content layers goes against best practice design principles and should be avoided in production code.

Using Neat allows the separation of these layers, resulting in clean, semantic HTML and CSS (via Sass) containing all the layout rules.  Consider this alternative example:

Grid columns in Neat

Possibly the most important concept to understand with Neat is that a column element must be a child of a container parent.  With the HTML example snippet above we can see the section element is the obvious container, with two child elements – article and aside.

And so let’s add some styling to create full-width (12-grid-columns) on mobile, and a two-column (8-grid-columns and 4-grid-columns) layout on “medium” sized devices.

At a glance, this all probably looks self-explanatory but let’s take a closer look.

Re-define Neat’s base grid

Neat’s default base grid is defined as:

This is applied to screen sizes smaller than the first media query breakpoint i.e. everything less than $medium-screen (768px) in our example above. Therefore, there’s no property for media in the default grid (more on this later).

As screen space is at a premium on mobile devices I like to reduce the gutter a little.  We can also change the number of columns to make the layout easier to work with:

Define your Neat Custom Grids

Out of the box, Neat defaults to 12 columns with a 20px gutter width but its real benefit comes from the flexibility of its grid system, being able to define custom grids and the number of columns, gutter size and media definition that is used by the grid. These are stored as a Sass map data type, e.g.

In a typical project I might have 3-4 Custom Grids defined, primarily to handle multiple media query breakpoints but also to increase the gutters and columns for those screen sizes:

Media queries

grid-media is Neat’s inbuilt media query function, taking a Sass map with the media property (i.e. the custom grids above) to determine when to change the layout based on the screen size.  Because we’re designing mobile-first, default styles are applied until the next specified breakpoint is triggered.

The grid-media function serves as a wrapper, applying any styles within it at the supplied breakpoint.

Changing the order of elements

Depending on your design and HTML you may find you need to re-order elements to achieve your desired layout.  For example, your HTML may look something like:

On mobile this would show as the featured image above the content but what if on desktops we want to position the content on the left and the image on the right?  Sure, we could do this manually with floats or absolute positioning but Neat makes this easy with the grid-shift function:

Based on a 12-column grid, this will effectively add position: relative to the elements and swap their position when the page is viewed on desktop screen sized devices.  The number entered will shift the element in a left-to-right direction.  Notice that we are using a negative value for the .content element to shift right-to-left.

Pushing grids

Easily confused with grid-shift above, grid-push adds left-margin to the grid instead.  Think of it more like adding (or removing!) spacing, rather than changing positions.  As with grid-shift, you can also use negative values to “pull” instead of push.

Common uses of this could be to push a grid column in to make the layout more visually interesting.

Columns shorthand

Setting out your column spans may be made easier by bypassing the grid and instead using shorthand to define the columns, letting Neat calculate the column spans for you.  I only discovered this feature recently and it’s probably easier to demonstrate how it can be implemented.

Assuming a grid of 12 columns, your column span elements might be set with:

As we can see, the total of the two grid-column values is 12, the total number of columns defined by our grid making the article and aside elements in our example fit 100% the width of their parent container.

The shorthand syntax simplifies this by allowing us to set the portion of the space the elements will occupy, e.g.

A nice bonus of this method is that we can easily apply column spans that wouldn’t normally fit neatly into a 12-column grid, such as a span of five columns:

Nesting Neat grids

This concept took me a while to wrap my head around and I still use this example as a reference.

The basic rule-of-thumb is that every time you define grid columns, they need to be wrapped with a grid container.  This is where the non-semantic style of other grid systems may have an easier learning curve as the markup is describing exactly what is taking place:

Neat grids are essentially the same, a row (grid-container) and within it a column (grid-column):

Collapsing containers

One byproduct of nesting grids is that you end up with double gutters (see the code example in Nesting Neat grids above).  Often when nesting you won’t want your inner grids to have left/right padding within their parent container so in these cases applying grid-collapse on the inner container will remove the padding and result in your nested columns sitting flush with the parent container.


When designing complex layouts, especially with a semantic structure it’s easy to lose your way. Here are some potential mistakes to watch out for that I’ve made using Neat grids:

Elements defined as both grid-container and grid-column

Remember the rule-of-thumb from earlier?  When used together grid-container and grid-column can appear to display correctly but when adding other mixins such as grid-collapse or grid-shift the outcome will be a mess of undesired width calculations and floated elements.  For an easier time with Neat, keep grid-container and grid-column separate.

Child of grid-container isn’t grid-column

The rule-of-thumb again.  Not setting grid-column on an element within grid-container will result in the element failing to align as desired.

Grid-collapse applied to grid-container

When applied to an element, grid-container styles an after pseudo-element as a typical “clearfix”:

Applying grid-collapse to an element sets negative margins and increases the width beyond its parent, so whilst using both grid-container and grid-collapse is perfectly valid it’s results are likely to be unpredictable and therefore should be avoided.

Using grids unnecessarily

Just because we have the Neat grid system at our disposal it doesn’t mean we have to Grid-All-The-Things.  Consider if there are there more appropriate ways to style your layout, e.g. Flexbox.

Combining @include and @extend

If your Sass coding style includes the use of extending selectors or placeholders with @extend, be aware that (at the time of writing at least) using @include and @extend together will result in an error when compiling.  An alternative is to create Sass mixins to create reusable code.  Further details of this can be found in Hugo Giraudel’s Sitepoint article.


For all of the examples above in one place, please see: this codepen

Hopefully, all these points will help you overcome any difficulties you’re having with Neat 2.0 grids.  If you have any feedback or questions get in touch with us on twitter @thehighriseteam.