CSS: Flexbox

The “Flexible Box” or “Flexbox” layout mode offers an alternative to Floatsfor defining the overall appearance of a web page. Whereas floats only let us horizontally position our boxes, flexbox gives us complete control over the alignment, direction, order, and size of our boxes.

Diagram: comparison of flexbox alignment, direction, order, and size properties
Diagram: CSS floats for text wrapping around a box versus flexbox for the rest of the page layout

flexbox overview

Flexbox uses two types of boxes that we’ve never seen before: “flex containers” and “flex items”. The job of a flex container is to group a bunch of flex items together and define how they’re positioned.

Diagram: flex container as a highlighted container wrapping grayed out elements versus flex items as highlighted boxes inside the container

flex containers

.menu-container {
  /* ... */
  display: flex;
}

This enables the flexbox layout mode—without it, the browser would ignore all the flexbox properties that we’re about to introduce. Explicitly defining flex containers means that you can mix and match flexbox with other layout models (e.g., floats and everything we’re going to learn in Advanced Positioning).

Diagram: Mixing and matching flexbox layout with block boxes and floats

aligning a flex item

After you’ve got a flex container, your next job is to define the horizontal alignment of its items.

.menu-container {
  /* ... */
  display: flex;
  justify-content: center;    /* Add this */
}

This has the same effect as adding a margin: 0 auto declaration to the .menu element. But, notice how we did this by adding a property to the parent element (the flex container) instead of directly to the element we wanted to center (the flex item). Manipulating items through their containers like this is a common theme in flexbox, and it’s a bit of a divergence from how we’ve been positioning boxes thus far.

Diagram: flex-start (3 left-aligned boxes), center (3 center-aligned boxes), flex-end (3 right-aligned boxes)

Other values for justify-content are shown below:

  • center

  • flex-start

  • flex-end

  • space-around

  • space-between

Try changing justify-content to flex-start and flex-end. This should align the menu to the left and right side of the browser window, respectively. Be sure to change it back to center before moving on. The last two options are only useful when you have multiple flex items in a container.

grouping flex items

Flex containers only know how to position elements that are one level deep (i.e., their child elements). They don’t care one bit about what’s inside their flex items. This means that grouping flex items is another weapon in your layout-creation arsenal. Wrapping a bunch of items in an extra <div>results in a totally different web page.

Diagram: wrapping two flex items in a <div> to eliminate one of the flex items
<div class='menu'>
  <div class='date'>Aug 14, 2016</div>
  <div class='links'>
    <div class='signup'>Sign Up</div>      <!-- This is nested now -->
    <div class='login'>Login</div>         <!-- This one too! -->
  </div>
</div>
.links {
  border: 1px solid #fff;  /* For debugging */
  display: flex;
  justify-content: flex-end;
}

.login {
  margin-left: 20px;
}

cross-axis (vertical) alignment

his is something that’s simply not possible with floats.

Diagram: justify-content (left and right), align-items (top and bottom)

The available options for align-items is similar to justify-content:

  • center

  • flex-start (top)

  • flex-end (bottom)

  • stretch

  • baseline

Diagram: flex-start (boxes at top of container), center (boxes in center of container), flex-end (boxes at bottom of container, stretch (boxes filling height of container)

Most of these are pretty straightforward. The stretch option is worth a taking a minute to play with because it lets you display the background of each element. Let’s take a brief look by adding the following to styles.css:

.header {
  /* ... */
  align-items: stretch;    /* Change this */
}

wrapping flex items

To create a grid, we need the flex-wrap property.

Diagram: no wrapping (boxes flowing outside of container), with wrapping (boxes wrapping to next line in container)
.photo-grid {
  /* ... */
  flex-wrap: wrap;
}

flex container direction

“Direction” refers to whether a container renders its items horizontally or vertically. So far, all the containers we’ve seen use the default horizontal direction, which means items are drawn one after another in the same row before popping down to the next column when they run out of space.

Diagram: row (3 horizontal boxes), column (3 vertical boxes)

Try adding the followingflex-direction declaration to our .photo-grid rule:

.photo-grid {
  /* ... */
  flex-direction: column;
}

alignment considerations

Notice that the column is hugging the left side of its flex container despite our justify-content: center; declaration. When you rotate the direction of a container, you also rotate the direction of the justify-contentproperty. It now refers to the container’s vertical alignment—not its horizontal alignment.

Diagram: axes flipped when flex-direction is equal to column

To horizontally center our column, we need to define an align-itemsproperty on our .photo-grid:

.photo-grid {
  /* ... */
  flex-direction: column;
  align-items: center;      /* Add this */
}

flex container order

Diagram: row (left to right), row-reverse (right to left), column (top to bottom), column-reverse (bottom to top)

The flex-direction property also offers you control over the order in which items appear via the row-reverse and column-reverse properties.

flex item order

This entire chapter has been about positioning flex items through their parent containers, but it’s also possible to manipulate individual items. The rest of this chapter is going to shift focus away from flex containers onto the items they contain.

Diagram: setting the order of a flex item individual with the order property

flex item alignment

We can do the same thing with vertical alignment. What if we want thatSubscribe link and those social icons to go at the bottom of the header instead of the center? Align them individually! This is where the align-self property comes in. Adding this to a flex item overrides the align-items value from its container:

.social,
.subscribe {
  align-self: flex-end;
  margin-bottom: 20px;
}

This should send them to the bottom of the .header. Note that margins (padding, too) work just like you’d expect.

You can align elements in other ways using the same values as the align-items property, listed below for convenience.

  • center

  • flex-start (top)

  • flex-end (bottom)

  • stretch

  • baseline

flexible items

Flex items are flexible: they can shrink and stretch to match the width of their containers.

The flex property defines the width of individual items in a flex container. Or, more accurately, it allows them to have flexible widths. It works as a weight that tells the flex container how to distribute extra space to each item. For example, an item with a flex value of 2 will grow twice as fast as items with the default value of 1.

.footer {
  display: flex;
  justify-content: space-between;
}

.footer-item {
  border: 1px solid #fff;
  background-color: #D6E9FE;
  height: 200px;
  flex: 1;
}

That flex: 1; line tells the items to stretch to match the width of .footer. Since they all have the same weight, they’ll stretch equally:

Increasing the weight of one of the items makes it grow faster than the others. For example, we can make the third item grow twice as fast as the other two with the following rule:

.footer-three {
  flex: 2;
}

Compare this to the justify-content property, which distributes extra space between items. This is similar, but now we’re distributing that space into the items themselves. The result is full control over how flex items fit into their containers.

static item widths

We can even mix-and-match flexible boxes with fixed-width ones. flex: initial falls back to the item’s explicit width property. This lets us combine static and flexible boxes in complex ways.

We’re going to make our footer behave like the above diagram. The center item is flexible, but the ones on either side are always the same size. All we need to do is add the following rule to our stylesheet:

.footer-one,
.footer-three {
  background-color: #5995DA;
  flex: initial;
  width: 300px;
}

summary

  • Use display: flex; to create a flex container.

  • Use justify-content to define the horizontal alignment of items.

  • Use align-items to define the vertical alignment of items.

  • Use flex-direction if you need columns instead of rows.

  • Use the row-reverse or column-reverse values to flip item order.

  • Use order to customize the order of individual elements.

  • Use align-self to vertically align individual items.

  • Use flex to create flexible boxes that can stretch and shrink.

Last updated