Bootstrap 3 grids
by Erik Flowers | August 19, 2013
After over 9 months of work, Bootstrap 3 is here. It introduces a new way of thinking on how the responsive grid works, when it is best applied, and how the styled elements within the breakpoints work as well. About a month ago, I decided I wanted to jump onboard right away, so I built a new blog theme with it (the one you’re seeing) and learned quite a bit more than I assumed I would. That’s what this post is about, sharing what I came to realize. So here’s a little guide, tutorial, and set of some examples to get you started.
Bootstrap 2’s grid was very straight forward. If you were using the fixed width containers, there was a normal, large, tablet, and mobile size. The base styles were all written within the context of the “desktop” width. Mobile styles were applied after through the responsive stylesheet. Compared to v3, it was very limited in out-of-the-box mobile convenience.
Bootstrap 3 has been heavily publicized as being mobile first. There’s been a design movement in the last year or two for “designing” mobile first, where you take your concepts and UX and plan it from the mobile perspective first, i.e. your interactions, wireframes, mockups, etc were all designed initially for the mobile experience. Bootstrap 3 has adopted that idea and built the framework on the idea that your base CSS and html should be from a mobile perspective by default.
Update 8/25/13: There’s been some questions around the ‘net about 100% width sites, “liquid” as we called it in the 90′s. I have added a section for that, click here to jump to it.
Update 9/27/13: If you like this article, be sure to read the Part 2 about a Bootstrap Less workflow here Bootstrap 3 Less Workflow Tutorial and the Subtle Magic Behind Why the Bootstrap 3 Grid Works.
Mobile First CSS
Great. So what does this actually *mean* if I’ve never done this before? Well, let’s just jump to a very simple example. Say you have an h1 tag at the top of your site. You design it up and check it out in your browser — looks great. Then you shrink it down to a mobile width, and the font is way too big! Here’s the thinking behind mobile first: Bootstrap expects that the styles you applied to the h1 are appropriate for the *mobile* widths. So if you chose your font size, padding, margin etc, at the desktop size, that will probably be way off at the mobile size.
Here’s an example of this:
<br> h1 {<br> font-size: 40px;<br> margin-bottom: 20px;<br> margin-left: 20px;<br> }
1
2
3
4
5
h1 {
font-size: 40px;
margin-bottom: 20px;
margin-left: 20px;
}
That is how you wanted it to look on the desktop, a nice big 40px font. But at a mobile size, it’s too big and the padding is too large. How would you have to do it with a mobile first CSS framework? Like this:
<br> h1 {<br> font-size: 22px;<br> margin: bottom 10px;<br> @media (min-width:@screen-tablet) {<br> font-size: 40px;<br> margin-bottom: 20px;<br> margin-left: 20px;<br> }<br> }
1
2
3
4
5
6
7
8
9
h1 {
font-size: 22px;
margin: bottom 10px;
@media (min-width:@screen-tablet) {
font-size: 40px;
margin-bottom: 20px;
margin-left: 20px;
}
}
See, the actual base style is the mobile style. Anything that you wanted changed at the next larger size is encapsulated in the @screen-tablet media query. Our font is sized at 22px by default, but at the desktop size it is at 40px. And, you can see that I didn’t need a margin-left on the base style, but I did add one in on the @screen-tablet breakpoint size, so it only applies when you’re past that min-width.
The Grid’s Basic Markup
For the markup that goes into your HTML, there are big changes. There are now 4 different grid classes you can use to define your layouts. This is where if you haven’t worked with a framework like this before, or you are accustomed to Bootstrap v2, it is a new way of looking at it. There are now 4 column size class variants:
- col-xs-*
- col-sm-*
- col-md-*
- col-lg-*
Now, before you panic and think “I have to write 3–4–5 freaking styles for every class I make?!” Probably not. Most of the time, the styles work fine at all the sizes, especially at the tablet and larger sizes. It’s only when you see specific needs at the larger sizes that you have to add in the adjustments. It is a small amount of time added, but:
- It’s way better than the old way of having whole mobile stylesheets and a “desktop first” CSS base.
- Once you get used to it, the flexibility and power will allay any doubts.
The premise is that the grid is controlled by the viewport size via the media queries and that as the browser width gets wider, the different column class will overwrite the previous. So at the phone width, the “xs (extra small)” column is active. But if you stretch your browser out wide, then the “lg (large)” class is active and overwrites the smaller sizes. If you’re confused, hang on and keep reading. This is a whole new Bootstrap paradigm. Instead of the elastic band approach of Bootstrap 2, v3 gives you now incremental control at each breakpoint.
Useful right? No? Don’t know? Let’s keep going!
Example 1 — Basic Single Columns
I am going to try and make these explanations as dead simple as possible. You have 2 divs you want to be each 50% of the total container
<br> <div class=””>I’m on the left</div><br> <div class=””>I’m on the right</div>
1
2
<div class=””>I’m on the left</div>
<div class=””>I’m on the right</div>
Now, in Bootstrap 2, we would have used the class .span6 for both. This would have given us the 50%/50% split at the tablet and up sizes, and then it would snap to the 100% width columns at the mobile breakpoint. Not so in Bootstrap 3. Since this is a mobile first framework, all of the base columns are assumed to be 100% width, stacked vertically. Huh? So in the example above, if you wanted these 2 divs to be 50%/50%, you would FIRST have to decide at which breakpoints. If you say “I want them to be 50%/50% down to the desktop size, but not tablet or phone”, it would be written like this:
<br> <div class=”col-md-6">I’m on the left</div><br> <div class=”col-md-6">I’m on the right</div>
1
2
<div class=”col-md-6">I’m on the left</div>
<div class=”col-md-6">I’m on the right</div>
This says “Make me a 6 column at the medium size and up.” Anything smaller than medium, it goes back to the 100% width stacked layout. This is mobile first, everything assumes that you are designing for a mobile, extra small viewport. So, let’s say you want it to be a 50%/50% split all the way down to the smallest phone width, no matter what. You use a different class for that, one that says “keep me as a 50% column all the way down to the phone size.” You would use the new “xs” extra small class:
<br> <div class=”col-xs-6">I’m on the left</div><br> <div class=”col-xs-6">I’m on the right</div>
1
2
<div class=”col-xs-6">I’m on the left</div>
<div class=”col-xs-6">I’m on the right</div>
This basically says “keep me at a 6 column width all the way down to the phone size, don’t ever switch me to the stacked mobile layout.” That means on a phone, it will still be a 50%/50% split on the columns since you used the specific col-xs-6 class. To take it the other direction, say you want to have the same divs be 50%/50% at the largest snapping point, and ONLY at that point. It’s just as easy:
<br> <div class=”col-lg-6">I’m on the left</div><br> <div class=”col-lg-6">I’m on the right</div>
1
2
<div class=”col-lg-6">I’m on the left</div>
<div class=”col-lg-6">I’m on the right</div>
That tells it to apply the “6 column” size at only the large size and up. As soon as you hit the break point going narrower, it will again assume that it’s a mobile design and take it to 100% width. I have made examples pages for this post, so Example 1 is demonstrating this most basic concept.
Mixed Width Columns
Now we have seen the basics of how the html markup classes work. But lets go deeper. Let’s use our 2 divs again and let’s give them the 50%/50% split at the medium viewport width:
<br> <div class=”col-md-6">I’m on the left</div><br> <div class=”col-md-6">I’m on the right</div>
1
2
<div class=”col-md-6">I’m on the left</div>
<div class=”col-md-6">I’m on the right</div>
Now, here’s where it’s new. Let’s say that you want it 50/50 at medium, but at large your design could really be better as a 33%/66%. So what we’re going to do is set it up to change the column widths at the breakpoint:
<br> <div class=”col-md-6 col-lg-4">I’m on the left</div><br> <div class=”col-md-6 col-lg-8">I’m on the right</div>
1
2
<div class=”col-md-6 col-lg-4">I’m on the left</div>
<div class=”col-md-6 col-lg-8">I’m on the right</div>
Does that make sense? Bootstrap is going to say “at the medium size, I look at classes with ‘md’ in them and use those. At the large size, I look at classes with the word ‘lg’ in them and use those.” In this case, our 2 divs will go from a 50%/50% split and then up to a 33%/66%. Just like that. This can be taken to another level, where we want to change it for the extra small phone size as well. Say we want to add the option for the columns to be split 25%/75% for tablets, we go like this:
<br> <div class=”col-sm-3 col-md-6 col-lg-4">I’m on the left</div><br> <div class=”col-sm-9 col-md-6 col-lg-8">I’m on the right</div>
1
2
<div class=”col-sm-3 col-md-6 col-lg-4">I’m on the left</div>
<div class=”col-sm-9 col-md-6 col-lg-8">I’m on the right</div>
Now this gives us 3 different column layouts at each point. On a phone, it will be 25% on the left, and 75% on the right. On a tablet, it will be 50%/50% again, and on a large viewport, it will be 33%/66%. 3 different layouts for each of the 3 responsive sizes! Check it out in example 2:
But, I know what some of you are thinking; that’s a lot of markup in your HTML, you could possibly use up to 4 different classes just for the grid. Some people mind that, some don’t. But there’s an answer to that too: mixins.
Mixin
Bootstrap 2 was set up to create columns from mixins, and v3 takes it even further. You can create your rows and columns purely from mixins and leave any grid markup out of your HTML. There are 2 basic mixin types for creating the grid:
- .make-row();
- .make-xs/sm/md/lg-column();
You use these mixins inside of elements that you want to serve those purposes. Here’s an example where I have a single div left-and-right that I want to be the row, and then left and right to be the columns inside:
<br> <div class=”left-and-right”><br> <div class=”left”>I’m on the left</div><br> <div class=”right”>I’m on the right</div><br> </div>
1
2
3
4
<div class=”left-and-right”>
<div class=”left”>I’m on the left</div>
<div class=”right”>I’m on the right</div>
</div>
Without grid column classes, these divs will just assume the default behavior of block level elements. Since we want to use the grid, but don’t want to use any markup, we’ll create the row and columns using mixins, (using Less, of course). Using the HTML above, a block of Less could look like this:
<br> .left-and-right {<br> .make-row();<br> .left {<br> .make-md-column(6);<br> }<br> .right {<br> .make-md-column(6);<br> }<br> }
1
2
3
4
5
6
7
8
9
.left-and-right {
.make-row();
.left {
.make-md-column(6);
}
.right {
.make-md-column(6);
}
}
That will add to those classes the properties of the col-md-6 that would go in the HTML otherwise. Using the mixins, you don’t have to include any markup in the HTML.
Going back to example 2 of multiple, different breakpoints on an element, you can do that with the mixins too. Once you know how you want the layout at each responsive size, you just add the column mixins within each media query. Here’s an example with mixins for all 4 layout sizes:
<br> .left-and-right {<br> .make-row();<br> .left {<br> .make-sm-column(1);<br> .make-md-column(7);<br> .make-lg-column(4);<br> }<br> .right {<br> .make-sm-column(11);<br> .make-md-column(5);<br> .make-lg-column(8);<br> }<br> }
1
2
3
4
5
6
7
8
9
10
11
12
13
.left-and-right {
.make-row();
.left {
.make-sm-column(1);
.make-md-column(7);
.make-lg-column(4);
}
.right {
.make-sm-column(11);
.make-md-column(5);
.make-lg-column(8);
}
}
This changes the column widths of .left and .right at each layout. In this wacky example, the side by side .left and .right would be jumping around pretty drastically, but the effect is clearly visible here in example three:
Pull/Push/offset
In both the HTML class and mixin method, offsets and pull/push work in the same way. You can include them as classes right in the markup, or dynamically include them as mixins. One difference between using the HTML markup and the mixins is that if you use the HTML method, at the tablet width the offsets are disabled and don’t change the layout in any way. If you want offsets to be in effect at tablets widths, you can include them as mixins. I am not quite sure why there is this difference, but there is.
With the pull/push abilities, you can easily flip where columns are positioned, moving them left or right at different breakpoints, which also can let them move up/down on full mobile view. It adds a lot of possibilities on top of an already powerful grid system.
Update: Full Width Fluid Containers
If you want to have a site that is the full width of the browser at all times, and “fluid”, you will have to make your own container class. It’s very easy. Since Bootstrap 3 is mobile first, the default state is the single column mobile width. So if you want everything bigger to function as just 1 responsive “100% fluid” width, you make a new container class and wrap your rows in it. Here’s an example:
<br> .my-fluid-container {<br> padding-left: 15px;<br> padding-right: 15px;<br> margin-left: auto;<br> margin-right: auto;<br> }
1
2
3
4
5
6
.my-fluid-container {
padding-left: 15px;
padding-right: 15px;
margin-left: auto;
margin-right: auto;
}
That should do it. I haven’t done extensive testing on this, but from the testing I did it does seem to work. All this does is take Bootstrap’s looking for .container and remove the media queries that set the widths. If you want to see it, it is at the bottom of Bootstrap’s variables.less:
<br> // Container sizes<br> // — — — — — — — — — — — — — — — — — — — — — — — — — </p><p> // Small screen / tablet<br> @container-tablet: ((720px + @grid-gutter-width));</p><p> // Medium screen / desktop<br> @container-desktop: ((940px + @grid-gutter-width));</p><p> // Large screen / wide desktop<br> @container-lg-desktop: ((1140px + @grid-gutter-width));
1
2
3
4
5
6
7
8
9
10
11
// Container sizes
// — — — — — — — — — — — — — — — — — — — — — — — — —
// Small screen / tablet
@container-tablet: ((720px + @grid-gutter-width));
// Medium screen / desktop
@container-desktop: ((940px + @grid-gutter-width));
// Large screen / wide desktop
@container-lg-desktop: ((1140px + @grid-gutter-width));
What you’re doing is just removing those set pixel values. And by adding back in the padding, you make sure that nothing touches the edges. The narrowest mobile size doesn’t need a fixed width since it’s always 100%, so you don’t have to set anything special for that.
There are some other techniques for putting fixed/responsive containers inside of liquid containers, and maybe I’ll come back to that if people care. Typically this comes into play if you’re doing something where you want a fixed-width sidebar for a nav or something, and then the rest of the right-side of the browser is fluid. This isn’t really a Bootstrap thing though, as much as it is putting Bootstrap inside of an outer scaffolding. I’ve done it before, and it’s cool, just takes some reworking of how Bootstrap sees the media query snap points, since it’s looking for viewport widths, but you’ve added things that push Bootstrap in either direction, so you have to account for that and add it to the media query… (this is another blog post topic).
Be warned — the various column sizes will still respond to the viewport width on when they change to the mobile view. You’ll have to decide how you want to do that. If you just want it to be simple and liquid, just use .col-sm-* for everything. Check it out in Example 4:
If you encounter any weirdness with this, post in the comments below.
Using Both Responsive Class Attributes and Mixin Columns
Taking everything we’ve learned so far, we can leverage both the CSS responsive attributes and the column mixins to basically do anything we want. This is closer to how an exaggerated real world implementation might look:
<br> .main-content {<br> .make-row();<br> .sidebar {<br> padding: 20px;<br> @media(min-width: @screen-desktop) {<br> padding: 30px;<br> }<br> h2 {<br> font-size: 20px;<br> @media(min-width: @screen-desktop) {<br> font-size: 30px<br> }<br> }<br> .make-sm-column(2);<br> .make-md-column(3);<br> }<br> .content-area {<br> line-height: 1.2em;<br> @media(min-width: @screen-desktop) {<br> line-height: 1.6em;<br> }<br> h1 {<br> font-size: 30px;<br> @media(min-width: @screen-desktop) {<br> font-size: 40px;<br> }<br> }<br> .make-sm-column(10);<br> .make-md-column(9);<br> }<br> }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
.main-content {
.make-row();
.sidebar {
padding: 20px;
@media(min-width: @screen-desktop) {
padding: 30px;
}
h2 {
font-size: 20px;
@media(min-width: @screen-desktop) {
font-size: 30px
}
}
.make-sm-column(2);
.make-md-column(3);
}
.content-area {
line-height: 1.2em;
@media(min-width: @screen-desktop) {
line-height: 1.6em;
}
h1 {
font-size: 30px;
@media(min-width: @screen-desktop) {
font-size: 40px;
}
}
.make-sm-column(10);
.make-md-column(9);
}
}
This essentially would let you have an entirely different layout at each responsive width, both in the grid and the styles altogether, and it’s not that much work to write in the Less. And as a bonus, by using the column mixins you don’t need to change anything in your HTML if you’ve already got it how you want it.
One of the things you have to get used to remembering is that the styles now cascade “up and out” from the base mobile CSS. Even though you can just design for the desktop view like normal, you will then have to basically “port up” the CSS from mobile widths and move the desktop styles into the right media query, and then fix/replace the styles at the base level. This isn’t a problem if you don’t care about how perfect things are at mobile widths. If you do want your site to be a great mobile experience, keep 2 browser windows open — one at the desktop width, and one at mobile. That way you can at least see when something is terribly out of place in either view.
Give em’ the boot!
Bootstrap 3 moves the whole paradigm of mobile first CSS forward, and makes it more accessible to the people who may have never done mobile first before. It’s more dynamic, flexible, and in the end I think will be easier to use.
All in all, I am very excited to use Bootstrap 3. I was a huge fan of v2, and v3 is such a step forward it’s hard not to marvel at the work that the @twbootstrap guys (@md0, @fat) and Github contributors have put into this.
Go get Bootstrap now and give it a try! If you have any comments, questions, want some help, have ideas or anything else, post in the Disqus thread below.
Like this article? Read the Part 2 about a Bootstrap Less workflow here Bootstrap 3 Less Workflow Tutorial and the Subtle Magic Behind Why the Bootstrap 3 Grid Works.
Examples: See Example 1 See Example 2 See Example 3 See Example 4
(As updates are made to Bootstrap 3, or my examples need refining, I’ll be updating this article and noting where I’ve done so)
Update 8/25/13: Added a section on making a 100% liquid container here.