What is flexbox?

Flexbox is a CSS display option that lets a container change the size of its children, such that the best possible layout is maintained across all display sizes. That's a mouthful, but it means that you can make sure your responsive components keep a great layout, without having to use javascript or do lots of absolute positioning or floats.

Example time, EXCELLENT!

Let's get started by bringing our basic page and a little styling in. I'm not doing anything special in the body, just making a main block as my container and then a series of boxes. I'll go ahead and put classes on each box so we can address them individually later. In the stylesheet, I'm going to give our main area a background color and a bit of margin and padding to make clear what changes happen as we apply rules.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Flexbox</title>
    <link rel="stylesheet" href="normalize.css" type="text/css">
    <link rel="stylesheet" href="typebase.css" type="text/css">
    <link rel="stylesheet" href="style.css" type="text/css">
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>
    <header>
      <h1>Flexbox</h1>
    </header>
    <main>
      <div class="one">1</div>
      <div class="two">2</div>
      <div class="three">3</div>
      <div class="four">4</div>
      <div class="four">5</div>
      <div class="six">6</div>
      <div class="seven">7</div>
      <div class="eight">8</div>
      <div class="nine">9</div>
      <div class="ten">10</div>
    </main>
  </body>
</html>
header {
  text-align: center;
  margin: 1rem;
}

main > div {
  width: 10rem;
  background: yellow;
  margin: 1rem;
  padding: 1rem;
}

main {
  background: lightblue;
  margin: 1rem;
  padding: 1rem;
}

Flex Contianer Properties

Now that we're all setup and good to go, let's start looking at the container properties that you can use with flexbox. We'll start off by adding display: flex; to our main element. With a refresh we see that now our divs are now horizontally aligned, and grow or shrink within reason to fit our page. We could also use inline-flex to make main an inline element. This is a great strategy if you are stacking multiple flex areas next to each other, for example product cards in a shopping site.

main {
  background: lightblue;
  margin: 1rem;
  display: flex;
}

Flex Direction

The first thing we should play with is flex direction. After we add that to the container, and can choose either row to go horizontal, or column to make it vertical. Additionally, we can add -reverse to either and have it go left-to-right or bottom-to-top, respectively. Let's look at a quick example of this:

main {
  /* snip */
  flex-direction: column-reverse;
}

By adding flex-direction: column-reverse; to our main element, we now have our divs counting down from 10, vertically. Let's revert that change to row before moving on.

main {
  /* snip */
  flex-direction: row;
}

Axis, Starts, and Ends

Just to have a clear model in your head about how this works, browsers track a handful of different pieces of data to make the flex calculations. Axis are one set of these points. The main axis is measured across the flex-direction with the cross axis being perpendicular to that. Each Axis has a start and end point where you would expect it, and they flip if you set a -reverse direction. Having this model in your head is important, because a lot of the later properties we'll cover use the axis and points as anchor positions. There is a great diagram on the MDN site and it's worth taking a few minutes to study.

Flex Wrap

With flex-wrap your options are nowrap, wrap, and wrap-reverse. By default, flex will keep all your items in a single row or column; this is nowrap.

main {
  /* snip */
  flex-wrap: nowrap;
}

If you need to build your items from the cross end then you'll want wrap-reverse.

main {
  /* snip */
  flex-wrap: wrap-reverse;
}

Here we can see that our items are built out left to right, bottom to top.

Often, you'll want them to roll over to the next line, just like normal inline elements would, this is when you would want to use 'wrap'.

main {
  /* snip */
  flex-wrap: wrap;
}

Luckily, this looks exactly like you think it should, and is probably the most common use case with flexbox.

At this point, we should be able to get our elements roughly in the right place, the final few properties determine how the elements take up that space.

justify-content

If you need to tweak how your items are placed along the main axis, then justify-content is what you are looking for. The first few properties are obvious:

  • flex-start: places the content starting at main-start
  • flex-end: places the content starting at main-end
  • center: centers the content midway along the main axis

Let's try adding a center property and seeing what it looks like.

main {
  /* snip */
  justify-content: center;
}

Our content is wrapped just like before, but the elements are all centered horizontally (since that is our main axis). The next two are a bit more confusing, so we should look at more examples.

If you want the space spread out between all the elements, with the first element touching main start, and the final element touching main end, then space-between is your best bet.

main {
  /* snip */
  justify-content: space-between;
}

Where as if you want to split the empty space evenly around all the elements, space-around will do that easily.

main {
  /* snip */
  justify-content: space-around;
}

align-items

To control how the cross axis is spaced, then you'll want to use align-items. We'll also need to add some height to our container to see how these work. Again the first three are trivial:

  • flex-start: places the content starting at cross-start
  • flex-end: places the content starting at cross-end
  • center: places the content midway on the cross axis
main {
  /* snip */
  height: 30em;
  align-items: center;
}

I think baseline is confusing. It aligns based upon the baselines of each of the affected elements so its great for lining up text. However, it can produce unexpected results when you have differing sized boxes. Let's make one of our boxes have some more content, so we can see how this works.

<div class="three">3<br />3<b3 /></div>

With center you can see that the threes aren't inline with the other text. Now if we cange to baseline you see that the top '3' is vertically aligned with the other numbers.

main {
  /* snip */
  align-items: baseline;
}

stretch is much easier, it just fills all of the available space along the cross axis.

main {
  /* snip */
  align-items: stretch;
}

Let's change that back to center before moving on:

main {
  /* snip */
  align-items: center;
}

align-content

To control spacing along the cross axis, between rows or columns there is align-content. Not to come as a surprise, but the first the first three are gimmies:

  • flex-start: places the content starting at cross start, leaving space at the cross end
  • flex-end: places the content starting at cross end, leaving space at the cross start
  • center: places the content in the center, with extra space split between the cross start and cross end

stretch has a gotcha. It obviously stretches the content to take up all space, though you'll need to drop any align-items as both can't be compensating for the available space:

main {
  /* snip */
  /* align-items: center; */
  align-content: stretch;
}

space-between and space-around work just like before, only on the cross axis. space-between locks the first and last row or column to the cross start and cross end.

main {
  /* snip */
  align-items: center;
  align-content: space-between;
}

Here we can see space-around distributing the space equally around all sides of both of our rows of content.

main {
  /* snip */
  align-items: center;
  align-content: space-around;
}

Summary

Today we looked at Flexbox and the properties that go on the flex container. We examined alignment and distribution, flow direction and spacing. Tomorrow we'll learn more about flex items, along with a couple layout basics that will make your life with flexbox much easier.

Resources