Video

Want to see the full-length video right now for free?

Notes

Neat is a lightweight, open source fluid grid framework built on top of Sass and Bourbon with an emphasis on flexibility and ease of use. It keeps all of the presentation code in the CSS, keeping classes like .col-sm-4 .col-lg-8 out of the HTML. Instead of prescribing class names, Neat allows the developer to define all of the classes which allows for much more semantic markup, like .sidebar instead of .col-sm-3.

Installing Neat

There are more detailed instructions in the Neat README.

  1. Add Neat to your Gemfile:
  gem 'neat'
  1. Then run:
  bundle install
  1. Import Neat in your application.scss, after Bourbon:
  @import "bourbon";
  @import "neat";

  // Other stylesheets go after bourbon and neat
  @import "users";

Using Neat

The first thing to do with Neat is establish the container that the grid will sit within. We do that with the outer-container mixin, which centers the element it's targeting, clears its floats, and sets its max-width.

To set the max-width to 1920px:

@import outer-container(1920px);

Note that this is the maximum width, not its absolute width. Neat is a fluid grid and is responsive to different screen sizes out of the box.

You can also set $max-width: 1920px in _grid-settings.scss.

Configuring Neat

We recommend creating a _grid-settings.scss file for Neat specific settings. Make sure to import it right before importing Neat:

@import "bourbon";
@import "grid-settings";
@import "neat";

@import "users";

In your newly created _grid-settings.scss, import neat-helpers if you are planning to use the new-breakpoint() mixin, then define your new variables:

@import "neat-helpers";

// Define grid setting variables, or don't specify anything and use the
// defaults
$column: 90px;
$gutter: 30px;
$grid-columns: 12;
$max-width: 1300px;

// Create screen size variables
$medium-screen-width: 600px;
$large-screen-width: 900px;

// Define your breakpoints (we'll touch on this later)
$small-screen: new-breakpoint(max-width $medium-screen-width 4);
$medium-screen: new-breakpoint(max-width $large-screen-width 8);

Why use a grid at all?

A 12-column grid is very common because it's evenly divisible by 2, 3, 4 and 6, which gives you a lot of flexibility to split up your layout.

With development, there are best practices for organizing modules and sections of code. When designing for the web, a grid system can help organize what's on the page. Grids are great for developers and users alike. They create consistency and allow the user to become familiar with the interface. Note that grids don't always need to be rigid or remain unbroken. Think of them as an aid that creates a great starting point for your layout.

Neat's mixins

span-columns

Now we can make our grid using the span-columns mixin.

If we have a 12 column grid (the default), and want our element to take up half of the width:

.my-element {
  @include span-columns(6);
}

Nesting columns

To work with nested columns (for example, having a 2-column element within a 6-column element), pass the number of columns of the parent to the span-columns mixin.

We could start a new 12-column grid, but that child grid would be very slightly (but perceptibly) misaligned with the parent grid. Instead, we should use Neat's built-in nesting features.

SCSS:

.my-element {
  @include span-columns(6);
}

.my-element-child {
  @include span-columns(2 of 6);
}

Generated CSS:

.my-element {
  display: block;
  float: left;
  margin-right: 2.35765%;
  width: 48.82117%;
}

.my-element:last-child {
  margin-right: 0;
}

.my-element-child {
  display: block;
  float: left;
  margin-right: 4.82916%;
  width: 30.11389%;
}

.my-element-child:last-child {
  margin-right: 0;
}

shift

Another common mixin is shift. This allows for spacing around columns that stays within our grid. Let's say we have content that we only want to span 8 columns (while still inside our 12 column grid from before).

We can start with this:

.skinny-element {
  @include span-columns(8);
}

This would create the correct size column, but it would be floated and aligned all the way to the left. To push it back to center:

.skinny-element {
  @include span-columns(8);
  @include shift(2); // (12 - 8) / 2
}

Responsive design

Beyond simple grids, Neat has useful functions and mixins for responsive design. It's a flexible, responsive grid framework, so it can target specific screen breakpoints. For example, on a phone you might not need 12 columns. You could use, say, 6 columns for a phone and increase it up to 12 columns on desktop.

We already showed the new-breakpoint() function in the _grid-settings.scss file. This allows us to store a media query in a variable to use in our grid system. (You can learn more about mobile-first design and breakpoints in our Weekly Iteration video on Responsive Design.)

To use a breakpoint in a media query (in this case, making a .card half width at the $tablet-up-breakpoint:

// _grid-settings.scss

$grid-columns: 8;
$medium-screen: 600px;
$large-screen: 900px;

// Use 8 columns when screen is >600px wide
$medium-screen-up: new-breakpoint(min-width $medium-screen 8);

// Use 12 columns when screen is >900px wide
$large-screen-up: new-breakpoint(min-width $large-screen 12);

We set $grid-settings to 8 so that if we don't specify a breakpoint, we use 8 columns, but can use 12 on large screens using the $large-screen-up breakpoint.

.card {
  @include fill-parent;

  @include media($medium-screen-up) {
    // span 4 of the 8 columns when the screen is >600px
    @include span-columns(4);
  }

  @include media($large-screen-up) {
    // span 8 of the 12 columns when the screen is >900px
    @include span-columns(8);
  }
}

omega

One useful pattern is using omega() to create multiple rows of columns without needing to wrap each with a row() element. This is great for things like photo grids, lists of cards or products, or any element where you'd like to remove the gutter margin. We can use omega to remove the right margin on every 3rd element (to make 3-element-wide rows). Without omega, the 3rd element is just barely too large to fit and will be bumped to the next row.

SCSS:

.product {
  @include span-columns(4 of 12);
  @include omega(3n);
}

Generated CSS:

.product {
  float: left;
  display: block;
  margin-right: 2.12766%;
  width: 31.91489%;
}

.product:last-child {
  margin-right: 0;
}

.product:nth-child(3n) {
  margin-right: 0;
}