If there's one thing flexbox excels at, it's twelve-column layouts. In a twelve-column layout, the page is broken into twelve invisible columns. These columns have small amounts of space between them, called gutters. The page is divided into rows, and the containers in the rows take up a certain number of columns.
If you start to look for them, you'll see twelve-column layouts everywhere. Take a look at these landing pages from Heroku, ChowNow and Square. Notice how the sections are broken up into halves, thirds and fourths?
In this article, I'll show you how to use flexbox's flex-grow
, flex-shrink
and flex-basis
properties to build twelve-column layouts, without the need for a library!
This article is an excerpt from Unraveling Flexbox, a book and video series on building flexbox layouts for the real world. If you like this post, be to check out the full series and subscribe to the Free Flexbox Starter Course.
Setting Up the Container
Let's say you want each of the <div>
elements in the following HTML to take up a third of the <section>
.
<section> <div class="column">First</div> <div class="column">Second</div> <div class="column">Third</div> </section>
By default, the <section>
element takes up 100% of the width of the screen. Start by limiting its width to 740 pixels. While you're at it, also add some space around the columns.
section { max-width: 740px; margin: 0 auto; } .column { margin: 10px; }
Pop open the code examples and try dragging your browser window until it's smaller than 740 pixels. Notice how the <section>
gets smaller as the screen shrinks, but stays fixed when the screen is larger than 740 pixels?
Flexin' It Up
Make the <section>
a flex container by setting it's display
to flex
.
section { max-width: 740px; margin: 0 auto; display: flex; }
By default, flexbox sets the widths of the columns to the size of their content. You can change this behavior by using the flex-grow
and flex-shrink
properties.
The flex-grow
property tells flexbox how to grow the item to take up additional space, if necessary. flex-shrink
tells flexbox how to shrink when necessary. Since we want the columns to behave the same while growing and shrinking, set both of these properties to 1
.
.column { margin: 10px; flex-grow: 1; flex-shrink: 1; }
Woohoo! The flexbox container now fills up three columns. The values for flex-grow
and flex-shrink
are proportional, meaning they change relative to other items in the flex container. Flexbox adds the values for the properties and then divides each column's value by that sum. So each column takes up 1 ÷ (1 + 1 + 1)
, or ⅓ of the total space.
What happens if one of the columns has a different value?
.column:first-of-type { flex-grow: 2; flex-shrink: 2; }
The first column takes up the same amount of space as the other two. That's because the values add up to 4
, so the first column is:
2 ÷ (2 + 1 + 1) = ½
The other two are:
1 ÷ (2 + 1 + 1) = ¼
All About That Basis
If you look closely at the last example, you'll notice that the first column doesn't quite cover half of the container. If you add more content to the third column, you can really see the problem.
<section> <div class="column">First</div> <div class="column">Second</div> <div class="column"> The third column, with more content than before! </div> </section>
What's going on? Why is flexbox not flexing correctly?
It turns out flexbox doesn't distribute space evenly to each column. It figures out how much space each column starts with, specified by the flex-basis
property. Then, the remaining space is distributed using the flex-grow
and flex-shrink
properties.
This might seem confusing, and that's because it is. The way this stuff adds up is really complicated, but don't worry, you don't need to understand the nuances to use flexbox.
Since we don't care about how much space the content originally takes up, set flex-basis
to 0
.
.column { margin: 10px; flex-grow: 1; flex-shrink: 1; flex-basis: 0; } .column:first-of-type { flex-grow: 2; flex-shrink: 2; flex-basis: 0; }
Tah-dah! It works! Well, kind of—there's one last thing to fix.
More Flex Basis
If you add another section below the first, you can see the problem.
<section> <div class="column">First</div> <div class="column">Second</div> <div class="column">Third</div> </section> <section> <div class="column">First</div> <div class="column">Second</div> <div class="column">Third</div> <div class="column">Fourth</div> </section>
.column { margin: 10px; flex-grow: 1; flex-shrink: 1; flex-basis: 0; } section:first-of-type .column:first-of-type { flex-grow: 2; flex-shrink: 2; flex-basis: 0; }
Why don't the columns line up? It's because flexbox includes the padding, border and margin in the basis when it calculates how big the item should be.
The first and second columns in the second row have 22 pixels between them (20 pixels for the gutter and 2 pixels for the borders). We can add this missing space to the first column in the first row by setting flex-basis
to 22px
.
section:first-of-type .column:first-of-type { flex-grow: 2; flex-shrink: 2; flex-basis: 22px; }
Shorthand
Together, flex-grow
, flex-shrink
and flex-basis
form the cornerstone of what makes flexbox flexible. Since these properties are so closely tied together, there's a handy shorthand property, flex
, that lets you set all three. You can use it like this:
flex: <flex-grow> <flex-shrink> <flex-basis>;
We can rewrite our CSS to look like this:
.column { flex: 1 1 0px; } section:first-of-type .column:first-of-type { flex: 2 2 22px; }
Ahh, that's better. Why the 0px
in the first flex
declaration? There's a bug in Internet Explorer 10 and 11 that ignores flex
if the basis doesn't include a unit.
That's It!
You've covered a ton of great stuff in this article, including flex-grow
, flex-shrink
and flex-basis
. You've also seen how these properties can be used to implement twelve-column layouts.
If you're looking for a challenge, try finishing off the entire grid. When you're ready, check the CodePen below to see how it was done.
See the Pen Flexbox 12-Column Grid Example by Landon Schropp (@LandonSchropp) on CodePen.
If you're still confused about how flex-grow
, flex-shrink
and flex-basis
work, don't worry. These properties are the hardest thing to understand about flexbox. You'll be reviewing them again in later lessons, including the next one, where you'll build an awesome video player layout! To make sure you get it, head over to the Free Flexbox Starter Course and sign up. Also, check out my full book, Unraveling Flexbox, for the complete series.