This tutorial is aimed at getting you started with Neat; a semantic grid framework built for Sass and Bourbon.
Bourbon Neat keeps your markup clean, preventing you from muddying it up with grid, column and row classes. Instead, it leverages mixins, and by applying its various mixins to your existing markup you can create flexible, responsive layouts. Let's explore the most essential mixins:
Note: In order to install and get started with Bourbon Neat, take a look at the previous tutorial Bourbon Neat: Semantic, Unopinionated, Responsive Grids.
outer-containerThis mixin is for determining your layout's container, or wrapper. Apply this to an element and Neat will automatically center it in the viewport (by adding margin-left: auto / margin-right: auto), clear the floats and apply the specified $max-width. It is an optional mixin (recommended though) and you can have multiple outer container elements on a single page. The one thing you can't do is nest them.
The outer container holds your grid. Within it, your grid can span as many columns across as specified in your grid-settings file via the $grid-columns variable (which defaults to 12 columns). All the elements in a row must add up to the total number of columns specified in this variable.
In the dummy example below, you'll see that the container element wraps a couple of aside and article tags. They span 3 and 9 columns respectively and add up to 12 columns as specified in my settings. If I were to go over that number of columns the layout would certainly break. Think of the outer-container mixin as the most likely prerequisite for adding consistent grid layouts within container elements.
.container %aside Aside: 3 columns %article Article: 9 columns %aside Aside: 3 columns %article Article: 9 columns %aside Aside: 3 columns %article Article: 9 columns
body background-color: white .container +outer-container background-color: #f5f5f5 aside, article padding: 10px margin-bottom: 20px height: 100px aside +span-columns(3) background-color: #81d4fa article +span-columns(9) +omega background-color: #e64a19
The background colors in this example make it easier to see how the pieces fit together. And don't concern yourself with the omega mixin at this point; all will be revealed in due course.
In your _grid-settings Sass partial you can also specify a $max-width Sass variable which defines the maximum width that the content of your page should span. For example, Neat comes with an easily changeable $max-width setting of 1088px (converted to em) out of the box.
There is also the option to provide this mixin with an argument for a $local-max-width if you want a certain container element to have a different max-width than the one set globally in grid-settings. Here, you can provide pixel, em or percentage arguments. The columns of your grid inside that container adjust their width automatically, but the number of columns stays the same.
.container +outer-container(800px) background-color: #f5f5f5
.container +outer-container(80%) background-color: #f5f5f5
If you are new to designing with grids, you should maybe look into the excellent Ordering Disorder: Grid Principles for Web Design by Khoi Vinh. I highly recommend it. One concept that you need to understand right away is that you build up your grid designs through a series of columns that span across the page.
The basic usage of this is super-straightforward with Neat. You pick an element, and tell it how many columns it should span within the total number of $grid-columns. Let me demonstrate the basics.
.container %aside.first First: 2 columns %article.second Second: 10 columns %aside.third Third: 4 columns %article.fourth Fourth: 8 columns %aside.fifth Fifth: 6 columns %article.sixth Sixth: 6 columns %aside.seventh Seventh: 8 columns %article.eighth Eighth: 4 columns %aside.ninth Ninth: 10 columns %article.tenth Tenth: 2 columns
body color: white background-color: white .container +outer-container background-color: #f5f5f5 aside, article padding: 10px margin-bottom: 20px height: 100px article background-color: #e64a19 aside background-color: #81d4fa .first +span-columns(2) .third +span-columns(4) .fifth +span-columns(6) .seventh +span-columns(8) .ninth +span-columns(10) .second +span-columns(10) .fourth +span-columns(8) .sixth +span-columns(6) .eighth +span-columns(4) .tenth +span-columns(2) .second, .fourth, .sixth, .eighth +omega
As you can see, every row consists of one blue aside on the left and one red article element on the right. The layout doesn't break, because within the outer container element their total number of columns and their width add up to 12 (as defined in $grid-columns) evenly.
The coolest part is that there is no need to add any styling information to your markup—since this is related to your presentation layer, you only define how your grid is composed within your Sass files. Cleanly separated concerns. Every sane designer that touches your work after you will love you for not polluting the content with styling information.
An added bonus is that you can name classes in your markup anyway you want or need. Nobody makes these decisions for you, which is a blessing without any disguise.
Nesting ColumnsFrom time to time it might come in handy to quickly nest grid elements within another.
.some-parent-element +span-columns(10) .some-nested-element +span-columns(5 of 10)
Say you have a wide element which spans for 10 columns and should incorporate two smaller elements spanning 5 columns each. In this case, provide the nested elements with the size of the parent column as an argument to the span-columns mixin. Let's look at a more concrete example.
.container %aside.first First: 2 columns %article.second %article.third Third: 5 nested columns %article.fourth Fourth: 5 nested columns
body color: white background-color: white .container +outer-container background-color: #f5f5f5 padding: top: 15px bottom: 15px aside, article padding: 10px margin-bottom: 20px height: 100px article background-color: #e64a19 aside background-color: #81d4fa .first, .second height: 250px .second +span-columns(10) .third, .fourth +span-columns(5 of 10) background-color: darken(#e64a19, 6) margin-top: 25px .first +span-columns(2) padding-top: 25px
omegaAnother important concept for newbies playing with grids is the gutter. This the margin on the right, between grid elements, and gets automatically created for every grid element in a container—except for the last! Gutters also scale responsively if you resize the browser window. The example below demonstrates this space beween grid elements. The gutter is signified by the grey-colored background which comes through from the outer container.
.container .first 1 col .second 2 col .third 3 col .fourth 3 col .fifth 2 col .sixth 1 col
body color: white background-color: white .container +outer-container background-color: #f5f5f5 .first, .second, .third, .fourth, .fifth, .sixth background-color: #81d4fa padding: 10px height: 200px .first +span-columns(1) .second +span-columns(2) .third +span-columns(3) .fourth +span-columns(3) .fifth +span-columns(2) .sixth
Easy-peasy right? But guess what happens if we double the columns by duplicating the row right beneath it?
Oh dear. So what happened here? As the sixth element in the first row is no longer the last element, it also gets a right gutter (margin) by default. Let me be very clear on this: to achieve a cleanly aligned layout, the last element in a container has its gutter removed by default. Because of the added gutter on the sixth element, the width of all elements in the first row now exceeds the total-width your number of total-columns can span per row and your grid breaks.
Nothing too tragic though, and the fix is easy. Just find the element that needs that gutter to the right removed and apply the omega mixin there. Done!
.container .first 1 col .second 2 col .third 3 col .fourth 3 col .fifth 2 col .sixth 1 col .first 1 col .second 2 col .third 3 col .fourth 3 col .fifth 2 col .sixth 1 col
body color: white background-color: white .container +outer-container background-color: #f5f5f5 .first, .second, .third, .fourth, .fifth, .sixth background-color: #81d4fa padding: 10px height: 200px .first +span-columns(1) .second +span-columns(2) .third +span-columns(3) .fourth +span-columns(3) .fifth +span-columns(2) .sixth +span-columns(1) +omega
Now, every element falls into place nicely, and none of the rows exceed their total-width.
Let's take this one little step further. Say you have a couple of rows that should display images of the same size evenly without breaking the grid. All we need is a couple of elements that span the same width, here span-columns(2), and place them in a couple of rows. The magic happens with the arguement you supply the omega with:
Here, every sixth img element will have its right gutter removed and therefore evenly fits six 2-column elements into the 12 columns of the outer container. Neat!
.container %img %img %img %img %img %img %img %img %img %img %img %img %img %img %img %img %img %img
body color: white background-color: white .container +outer-container background-color: #f5f5f5 img +span-columns(2) +omega(6n) height: 200px margin-bottom: 5px background-color: #81d4fa
You want only four elements per row? No problem! Reduce the argument for omega to 4n. This technique will come in handy during the next tutorial when we get to responsive grids and how you can change your layout through media queries.
I encourage you to play around with this example via the provided pens and get a feel for it. There is no magic here, but don't be surprised if you need a bit more time to wrap your head around the details. Mess a bit with the arguments of the omega and I have no doubt it will become crystal clear to you in no time.
Last words of wisdom: In some cases it seems to matter in which order you supply the span-columns and omega mixins to the elements. My advice is to always apply span-columns first to avoid unexpected behaviour.
shiftThis mixin should be quick. If you want to adjust an element by moving it horizontally to the left or right, you can apply the shift mixin, and provide it with the number of columns it should move. You can use integers or floating point numbers.
Provide a positive number (unitless) of columns to move the element to the right and vice versa. Behind the scenes, Neat increases or decreases the percentage values of margin-left on the element.
Note: if you use shift without an argument, it will default to shift(1).
shift-in-contextThis mixin has the same idea as shift (it uses shift-in-context under the hood) but is made for grid elements that are nested. I've played around with it a little bit in a dummy example with nested grids, but in all honesty I achieved the same results using shift.
padI don't think I need to go into any specifics of how this works. It's a little helper to clean up your stylesheets and to give you the default gutter width if you provide the mixin with default as an argument. Nothing too fancy, but I thought I'd mention it to complete your options for adjusting the spacing of your grids.
.some-element-that-needs-padding +pad(10px 20px 30px default)