Flexbox

Flexbox is a modern and robust system for positioning elements in CSS. It is built into modern browsers, so there is nothing to install. you only need to have display: flex on your parent element to start using it.

div {
  display: flex;
}

Flexbox is all about parent-child relationships. It is a dynamic way of positioning children elements relative to their parent.

There are a number of Flexbox attributes, and each of those attributes has a number of values. Each attribute has a default, so unless you override this, your elements will default to that position.

Let's build a CSS file that we will use for using flex.

.child {
    width: 50px;
    height: 100px;
    background-color: lightcoral;
    border: 9px solid white;
}

.parent {
    display: flex;
}

We will have a child element that we will set inside the parent so show how to use the parent to position its children.

We've given the child some height, width and color so we can see it, and a border so that we can distinguish between children.

Let's see them in action in some HTML:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div class="parent">
    <div class="child"></div>
    <div class="child"></div>
    <div class="child"></div>
  </div>

</body>
</html>

Run this HTML file and we can see that the default position for these three elements are next to each other on the left.


Flex-direction

Flex assumes that we want to be working in "rows." But what if we want to be working in "columns"?

We control this with flex-direction.

flex-direction has four possible values.

  • row (default) - Left to right
  • column - Top to bottom
  • row-reverse - Right to left
  • column-reverse - Bottom to top

Try each of those options on the parent element to see what is does to the children. Starting with:

.parent {
    display: flex;
    flex-direction: column;
}

Testing these different attributes is done easiest in the developer tools.

When we start working with Flexbox, we must first decide which flex-direction we want to be worrying about. Usually this will be the default row.


Justify-content

What if we want our children evenly spaced across our parent, or spaces in the center or end of our parent?

We can achieve that with the justify-content attribute.

justify-content has 5 different available values:

  • flex-start - Default value. Items are positioned at the beginning of the container
  • flex-end - Items are positioned at the end of the container
  • center - Items are positioned at the center of the container
  • space-between - Items are positioned with space between the lines
  • space-around - Items are positioned with space before, between, and after the lines

Use each one of these in your parents CSS. Understand them. Use them with different flex-direction attributes.

Notice the subtle difference between space-between and space-around


Align-items

We are going to make our parent tall for this one. Give it a height of 500px.

.parent {
    display: flex;
    height: 500px;
}

Align-items has 5 different attributes.

  • stretch (default) - Divs and other elements without a specified height will be the full height of the parent.
  • center - Aligns things in the center vertically if flex-direction is row, and horizontally if flex-direction is column.
  • flex-start
  • flex-end

The "start" or the "end" depends on flex-direction. Think of it like reading a book. You start from the top and read down. The top is the beginning, or the start. With flex-direction: row, align-items: flex-start will align items at the top and align-items: flex-end at the bottom. Even with flex-direction: row-reverse, it's still like a book. The start is the top.

With flex-direction: column, the start is the left. Like reading a book. With column-reverse the start is still the left.

Play around with all these different combinations until you can accurately guess what values will position your children where.


Align-self

Of course we need to account for one offs. Let's give one of our blocks a special class.

<div class="parent">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child one-off"></div>
</div>

align-self has all the same alignments has align-items. Play around with this one off in Chrome's dev tools for a bit.


NOTE: There is a lot to Flexbox. Now may be a good time to review what you've learned, practice and apply it, and once it's second nature, come back for more.


Flex-grow

flex-grow will be applied to the children. We can use it to fill the parent. The flex-grows value is a number and works off ratios. If you want all the children evenly spaced, we will use flex-grow: 1.

If you wanted your one-off child to fill half the space, and the other two children to fill the other half of your parent, what value would you give each?

flex-grow: 2 to the one-off and flex-grow: 1 to the other children is correct.

If you want your child to just fill it's default amount of space, use flex-grow: 0.

Practice with flex-grow until it makes sense to you.


Flex-shrink

flex-shrink handles how children should behave if the parent becomes to small. It works with ratios just like flex-grow.

flex-shrink defaults to flex-shrink: 1.

Let's test this out.

.children {
    width: 100px;
}

.one-off {
    flex-shrink: 2
}

Use the Chrome developer tools to change the width of the parent. highlight the pixel width and press the arrow keys up and down to adjust it. Hold down command to adjust it in increments of 10.

We see that the one-off shrinks to half the size of the other two. Or, 2 times the amount.

If we do not want the child to adjust it's size, we can set it to flex-shrink: 0;

Flex-basis

Your flex-basis is your width or height. Width when using flex-direction: row and height when using flex-direction: column. It trumps height or width.

If there's not enough space then the children shrink according to their flex-shrink ratios. And if there's extra space available they can expand to fill it according to their flex-grow ratios if they have any.

flex-basis defaults to flex-basis: auto, which means to fallback to the width (or the height when flex-direction: column).


Flex

Instead for using grow, shrink, and basis, you can just use flex. The value of flex is three values, grow, shrink, and basis in that order.

It defaults to 0 (grow) 1 (shrink) and auto (basis).

Let’s simplify down to two boxes.

Here are their properties:

.square#one {
  flex: 2 1 300px;
}
.square#two {
  flex: 1 2 300px;
}

Both have the same flex-basis. That means if there’s enough space for both of them (the container is 600px plus room for margins and padding), they will both be 300px wide.
But as the box grows, Square 1 (with the higher flex-grow) will grow twice as fast. As the box contracts, Square 2 (with the higher flex-shrink) will shrink twice as fast.
All together now:


flex-grow, flex-shrink, and flex-basis are important attributes to use to be able to learn. Practice with these attributes. Practice using just flex too.


Flex-wrap

flex-wrap specifies whether flex items are forced into a single line or can be wrapped onto multiple lines.

It's most useful values are:

  • flex-wrap: nowrap; - Items are forced onto a single line
  • flex-wrap: wrap; - Items will wrap if there is not enough room

Use this for making your elements responsive.