Bootstrap v4 explained: The grid and how to use it

Gijs Boddeus
Afosto
Published in
10 min readJan 23, 2018

When you browse through the #help channel on the Bootstrap Slack workspace, you will see a few questions being asked over and over again. In this series I will try and answer these questions thoroughly in the hopes you will understand what techniques are used and how to use it properly.

Today I’ll explain the scss techniques used to create the grid and how to use the classes in your html. You can read through the documentation on getbootstrap.com

If you just want to know how to use it, scroll down till the next three dots.

Techniques

Back in the day people had to create grid structures with tables (actually a hack), then with floating divs (also a hack), now we use flexbox (still a hack) and if you’re really up to date css grid (not a hack!). earlier versions of Bootstrap used the float technique, but it had it’s caveats. Version 4 introduces a grid based on flexbox. If you don’t know how flexbox works, here are some links to learn about it.

Container

The .container is a really simple element. It gets a padding equal to half of the gutter width. It also gets centered by adding margin-left: auto; and margin-right: auto;. The width of the container is generated by the make-container-max-widths() mixin. It creates a media query for every breakpoint and adds max-width: [max-width];. The .container-fluid class is exactly the same but without the max-widths, it takes up the full width of your screen and only has the padding.
Here’s the scss mixin that creates it:

@mixin make-container() {  
width: 100%;
padding-right: ($grid-gutter-width / 2);
padding-left: ($grid-gutter-width / 2);
margin-right: auto;
margin-left: auto;
}

For the widths scss the mixin looks like:

@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {
@each $breakpoint, $container-max-width in $max-widths {
@include media-breakpoint-up($breakpoint, $breakpoints) {
max-width: $container-max-width;
}
}
}

Don’t be frightened by all the variables. What this mixin does is: create a media query for every value in $grid-breakpoints and add a max-width rule into the media query based on the corresponding value in $container-max-widths.

Row

Flexbox by default aligns items on a single row and starts it on the left. It also defaults to flex-wrap: nowrap , this means it will align all items side by side, even if they don’t really fit. So, Bootstrap sets this property to wrap to make it possible to break columns intro more rows without adding it to as html markup.
The scss used for the .row are just this:

@mixin make-row() {
display: flex;
flex-wrap: wrap;
margin-right: ($grid-gutter-width / -2);
margin-left: ($grid-gutter-width / -2);
}

It uses flex(box) as the display setting, tells it to wrap instead of overflow and adds negative margins to compensate for the padding on the container. By default these are -15px (30px / -2).

Additionally the .no-gutters class can be added to the .row element. This adds styling for the row and the columns that are direct children of it. The styles added are:

.no-gutters {
margin-right: 0;
margin-left: 0;
> .col,
> [class*="col-"] {
padding-right: 0;
padding-left: 0;
}
}

This removes the negative margin from the row and positive padding from the columns inside te row.

Columns

The columns are the hardest to understand in my opinion. Since we’re harnessing the power of flexbox, Bootstrap uses flex: 0 0 [col-width]; to set the width of the columns.

First thing is the general styling added to every column class.

position: relative;
width: 100%;
min-height: 1px; // Prevent columns from collapsing when empty
padding-right: ($gutter / 2);
padding-left: ($gutter / 2);

Not a lot of new things going on here. What might throw you off is the width: 100%; on the second line. This is just a default to stretch the column. The padding gets added by default too with the same as the container.

To create a structure we need to be able to define the width of column. Bootstrap uses a twelve column grid. This means we can use any number from 1 trough 12 to define it’s width. For example: to get 2 even width columns next to each other, use the number 6 for both column classes.
The actual lines that add the width to each column class are:

@mixin make-col($size, $columns: $grid-columns) {
flex: 0 0 percentage($size / $columns);
max-width: percentage($size / $columns);
}

What the percentage($size / $columns) does is taking a width like 6 and divides it by the number of columns, by default 12, and calculates a percentage with it. So for col-[infix]-6 it will print out 50%. The outcome of the percentage function is used in both lines. As the flex property is a shorthand it also gets a flex-shrink and a flex-grow value of 0 to ensure it keeps the defined width. The max-width is a fix for IE and Firefox.
Now this is all we need to make a grid, though it is not responsive yet. For that we need to setup the classes for columns 1 through 12 for each breakpoint. Now this is a pretty big mixin so bear with me here…

@each $breakpoint in map-keys($breakpoints) {
$infix: breakpoint-infix($breakpoint, $breakpoints);

This first part sets a variable to use as an infix for the column classes, by default: sm, md, lgand xl. Note that xs is not used in any class in v4. This is due to the mobile first approach, so the starting point is xs. I.e.col-6 is the class for a 50% width column for every screen width.

@include media-breakpoint-up($breakpoint, $breakpoints) {
.col#{$infix} {
flex-basis: 0;
flex-grow: 1;
max-width: 100%;
}
.col#{$infix}-auto {
flex: 0 0 auto;
width: auto;
max-width: none;
}
...

Here we are at the start of creating the classes for each breakpoint using the media-breakpoint-up mixin and passing the breakpoints map to it. So for each breakpoint this will create two classes that work a little different from the number classes. The first class will stretch the column for as long as it fits, given it’s content.
The second class will overwrite the default styling so it’s not a 100% by default, it will just be as wide as it’s content.

  ...  @for $i from 1 through $columns {
.col#{$infix}-#{$i} {
@include make-col($i, $columns);
}
}
...

Here we actually create the classes we can make the grid responsive with. It loops through every number starting at 1 and ending with the defined number off columns, by default this is 12. It combines the fixed .col and, when it’s not the smallest breakpoint, the earlier defined $infix with the counter ( $i ) to create the class name. It uses the make-col() mixin I explained earlier to add the lines for flex and max-width.

  ...  .order#{$infix}-first {
order: -1;
}
@for $i from 0 through $columns {
.order#{$infix}-#{$i} {
order: $i;
}
}
...

Here we create the useful order classes for each breakpoint an each option from 0 to 12, again using the infix for the breakpoint. The first class will set the column to the first position regardless off its position. More on these classes in the docs.

  ...  @for $i from 0 through ($columns - 1) {
@if not ($infix == "" and $i == 0) {
.offset#{$infix}-#{$i} {
@include make-col-offset($i, $columns);
}
}
}
}

And for the last part we create the offset classes. These classes add a margin-left based on the same percentage as the width for the columns. Link to the mixin.

This concludes all the scss magic done for you by the Bootstrap package. Now that we have all these classes, how do we use them in our html?

Using the classes in HTML

Most of the times this is where people get confused. The main thing is knowing when to add which class on what element. So to keep going in the same format, we’ll start of with the container.
You can copy the examples below and us this in a codepen, I have a template setup with v4-beta3 which you can find here.

Container

The container sounds pretty straight forward, but not to everyone. It has been confused as a row, or used nested in another container. The container should always be the outer most element in your website. So starting with a little code:

This could be the start of your website. The yellow bar is the container element, it is centered by the margin on the x axis with the auto value and has a fixed width. You can use the container-fluid class if you want to make a full width site.
to get the text in the header and footer to align with the text, you can place a div inside the header or footer and the container class. That way everything lines up.

So to be clear: this is the only thing it should be used for. The outer most element so everything aligns vertically. It can be nested in other elements, but these should not have width, margin or padding settings.

Row

The row should be a direct child of the container. This is what you should adhere to but you can deviate from this. In the example we have a row in the container with a blue background.

You might notice you don’t see the yellow anymore. Thats due to the negative margin on the row. Remember? The container adds 15px of padding on the left and the right, the row adds a margin of -15px to the left and the right to accommodate the padding on the column.
Wrapping the row in another element should be allright, but to be on the safe side only use rows as a direct child of a container or of a column.

Column

This is where the magic happens.
The first rule you really need to stick to is: columns can only be children of a row, and I’m serious here. Do not use it in any other way, only if you fully understand how flexbox works and you know all the caveats of using it in any browser. Using theses classes the wrong way can really mess up your layout in some browsers.

Ok now let’s have some fun.
If we take the example above and add the most basic column class we have to it, .col, we will see it line up with the container again.

you can see the column is exactly as wide as its parent ( the row ), but has a padding of 15px to align with the container again.

In the example below you can see a basic even width three column layout. In this example this layout is exactly the same across any screen width. That is due to the use of col-4. This class means “Take up 4 of the 12 columns, on every screen width”.

Now lets make it responsive, it’s really easy.
All we need to do is modify our column classes. We will need a default and add a breakpoint to align the columns next to each other. As Bootstrap v4 is created with mobile first in mind, the default will be for the smallest screen. To do so the class col-12 will give us a full width column. On bigger sizes we want it to go back to three side-by-side columns, we can do this by using col-md-4. What these two classes will tell the browser is: “On small screens you stack on top of each other and take up all 12 column. On screens like tablets and bigger take up 4 of the 12 and let other columns go beside it.”

Now we have responsive layout we can use in our project. The next example is somewhat a real world use.

Yes that is Nicolas Cage… he can play anything.
Same layout as the example above, but with some content in it.

Nesting grids

You can also nest grids into each other, wel you can start another row inside a column and use columns in it. Golden rule: NEVER NEST A CONTAINER.
The order to nest is and can only be:

.container
.row
.col
.row
.col
// etc.

or if this clarifies it better: .container > .row > .col > .row > .col > //etc. This is the one thing most people seem to misinterpret about the grid. 2 common misunderstandings: using the container as a row and nesting containers inside columns.

The yellow block is a row that is nested inside the red column.

No gutters

optionally, I don’t really use it, you can add the class no-gutters to the row to get rid of the gutter between the columns. It still respects the padding of the column but removes the negative margin of the row and the padding of the columns.

As you can see the red and the blue column now have no gutters and are snuck up to each other. Notice that i only added the class to the outer row, not the nested row. As you can see the yellow row still respects the gutters. The row has a negative margin on the left and the right, thus placing the nested columns right up to the outer column edges.

Et voíla

Thats the basics of of how to use the grid. Use it wisely and keep this in mind:

.container
.row
.col
.row
.col
// etc.

Here are some more advanced examples to learn from. They are entirely made up out of bootstrap components, plus some awesome pictures 😉.

Product grid

Banner grid

You can go all kinds of crazy with the grid, use your imagination and explore the possibilities.

Thanks for reading, hope you learned something.
Next up on the list: Display utilities, the new hiding and showing

--

--

Gijs Boddeus
Afosto
Editor for

Frontend developer @ Afosto, creating ecommerce tools and stores.