Crafting Twelve-Column Layouts with Flexbox

By  on  

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.

A twelve-column grid with columns and gutters

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?

Examples of twelve-column layouts from Heroku, ChowNow and Square

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.

Landon Schropp

About Landon Schropp

Landon is a developer and entrepreneur based in Seattle. He's the author of the Free Flexbox Starter Course and Unraveling Flexbox, a book on how to create modern, responsive layouts in CSS. He's passionate about building simple apps people love to use.

Recent Features

  • By
    JavaScript Promise API

    While synchronous code is easier to follow and debug, async is generally better for performance and flexibility. Why "hold up the show" when you can trigger numerous requests at once and then handle them when each is ready?  Promises are becoming a big part of the JavaScript world...

  • By
    9 Mind-Blowing WebGL Demos

    As much as developers now loathe Flash, we're still playing a bit of catch up to natively duplicate the animation capabilities that Adobe's old technology provided us.  Of course we have canvas, an awesome technology, one which I highlighted 9 mind-blowing demos.  Another technology available...

Incredible Demos

Discussion

  1. I have been using responsive grid frameworks for the longest time. How have I never heard about this before. Thank you for the heads up! I am now off to check out browser support for these features.

    • You’re welcome Trevor! Browser support for flexbox is actually pretty good right now at 95%.

  2. very good tutorial. One thing missing here is the offset features of the grid which are available in twitter bootstrap. I hope you will cover that in your next article.

    • Yep, offsets are a little bit trickier. In order to do them responsively, you have to use percentages, which requires you to know the “total” number of columns. For example, if you’d like for two center columns to be offset by two columns on the side, then you need to add a 25% left margin to the first column and a 25% right margin to the second column.

  3. Very great explanation of how to make simple grid with flexbox. There are maybe some tricks I can take to make more better mine you can find here if you want: http://gridlex.devlint.fr

  4. A. M. Douglas

    Take it from someone who wasted time making a flexbox/calc grid framework: wait for the CSS3 Grid spec to land in browsers.

    • What was the issue with your flexbox/calc system?

  5. This is really cool – thanks Landon!

  6. I’m loving all the different viewpoints which flexbox has unraveled. It’s just so flexible – bad pun I know.

  7. Oliver

    Wow, how cool….. thx for sharing this. If we need more complicated solutions may be we can use lost-grid from Cory Simmons where we can include flexbox and calc

    https://github.com/corysimmons/lost#global-grid-settings
    @lost flexbox flex;

  8. Thanks a lot Landon, learning about Flexbox has been in my long list of to-dos for a while, i now pretty much clear on how it can be used to setup a 12 grid layout. I need to learn more on how the responsiveness is implemented though.

  9. Dnd

    Nice example. However I wonder how you would work with breakpoints as I guess nobody wants 3 columns shrinked on a small device for example.. And having them dropping on the next line using flex-wrap: wrap; is not, in many case, an option.

    So how would you rearrange the size of the elements inside that section if, let’s suppose, you have a few breakpoints (ie: 480, 600, 840, 960, 1280, 1440, 1600; these a google material design breakpoints). How would you do to set your element to be full width below 960 and to be a third beyond that?

    It feels like we touch to some flexbox limitations here, which makes me follow the ones that are saying flexbox should never be used for “layouting”. The css grid property, when it will be available seems far better than flexbox in my opinion. For the layout purpose anyway.

    Any tips on how you could achieve this with a pure flexbox solution?Because this is where it really starts to be a bit confusing..

    Anyway, thanks for the tutorial, which is very interesting indeed!

    • You could manipulate flex-basis with media queries.
      flex-basis to 100% on an item, even in with unwrap (defaut) property on the parent, will take the full width, pushing other elements below.
      Personally, I use JS to re-arrange blocks visually, not necessary in the same order, as I found the defaut “responsive” behavior not always suited for my content, I’m not fond of one serialized big column for mobile.
      In order to achieve that, I duplicate blocks of content (CMS-generated) and Hide/Show then depending on the viewport size. So no need to achieve complicated CSS tricks or JS DOM manipulation. Only downside : more byte to load on the page (but that’s mostly text or cached content anyway).
      Dirty, but most efficient wait to re-arrange completely the layout.

  10. Hello there,
    I bought the book and reading chapter 5
    and I’m wondering
    Where is the golden ratio of 1.61803 come from ?
    Thanks in advance

    • Hakim Jonas Ghoula

      It comes from math or from nature. If you read about ‘the fibonacci sequence’ on Wikipedia or find a documentary you will understand and be amazed ☺️.

    • Thanks so much and sorry for the silly question I realized it just a few seconds after I send the email :)

  11. Emily

    That’s a good article on Flexbox itself, but Flexbox should not be used for page layouts, it’s not what it was designed for and the W3c itself says it shouldn’t be used in this way. It’s table layouts for pages all over again (without the solid browser support).

    Its far simpler easier to use %. There are loads of resources out there to find the maths/figures for good percentage grids.

    In about 9 years time we’ll all be able to use CSS grid across the board thankfully, which is amazing.

  12. Emily

    Also, the 95% support for browser usage is very misleading. That’s no-doubt based on figures supplied by organisations like W3 schools and Can I Use. They get their browser usage figures from people who are web-designers/ devs visiting site their sites. The total support amongst the public usage of browsers for Flexbox would be around 75-80%ish.

    Don’t forget 6% of computers used in the Western World still actively use IE8.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!