How to finally understand CSS flexbox 
Tags: css, tutorial
Published: 2020-11-13 17:04:14

Have you read multiple articles on flexbox and still feel you don't fully understand it? You're not alone.

The problem with how flexbox is taught is that the most important property is taught last. By the time you get to it, you have to mentally juggle dozens of combinations of the less important ones. In this article, I will walk you through all the concepts in an order that makes more sense to me, and hopefully to you as well.

# 1. Forget everything about the parent container

Forget everything about the parent except `display:flex`. Think of flex as items in one line. The line may be vertical or right-to-left, but for now, it's a line.

# 2. Forget about flex-grow and flex-shrink

Set `flex-grow` and `flex-shrink` to 0. Forget them. You're basically in `display:inline` world, except it doesn't wrap yet. This is what we have from now: 

{% codepen https://codepen.io/galoisgirl/pen/wvWNMNr %} 

# 3. Learn `flex-basis`

This is the most important property. Learn what values `0`, `auto` and `50%` do. That's the starting point for your child elements widths. 

You can play around with the Codepen below, or read [this excellent article by Dave Geddes](https://mastery.games/post/the-difference-between-width-and-flex-basis/), whatever you wish.

{% codepen https://codepen.io/galoisgirl/pen/jOrdqOv %} 

Now just for a minute, think of `flex-basis` as the width of the child elements.

# 4. Compare the width of the parent with the total width of the children

## 4a. When the parent is bigger

You may want to have the children grow. All of them equally? Only the last one? Does one child deserve more? Try different combinations of `flex-grow`.

## 4b. When the parent is smaller

You may want to have the children shrink. Just like `flex-grow` redistributed remaining space, `flex-shrink` will redistribute negative space. Again, it can take from all children equally, from only one, all but one... 

Whatever width an element will have **after** this step will be his true `width`. His `flex-basis` is what was **before**.

# Made it so far?

Congratulations! You know 90% of what there is to know about flexbox. If you've been reading about flexbox already, you probably know everything else too. But, on the off chance you want to keep reading, I'll go on.

# 5. Two more properties for the children: `order` and `align-self`

The property `order` lets you re-order child elements at will. Keep in mind that accessibility rules say [the visual order of elements that form a meaningful sequence should match their order in the DOM](https://www.w3.org/TR/2016/NOTE-WCAG20-TECHS-20161007/C27).

If a child element has a smaller height than the parent, you may want to center it vertically or align it to the top: `align-self` does just that. Since, as I said at the start, our line may be vertical or right-to-left, this property doesn't use keywords like "top", opting for the flexible `flex-start` and `flex-end`.

OK, we're done with the children! To the parent now.

# 6. Properties of the parent element

## `Flex-direction`

When I said "the line can be vertical", that's what `flex-direction: column` does. Whatever I said about `flex-basis` as a width would then be about height. Same concept, different direction.

## `Flex-wrap`

While `flex-wrap` may be obvious in itself, it can be tricky when combined with other properties.

### `Flex-wrap` and `flex-grow`

Let's try an example. Below is a 500px parent (red) with three identical children (blue) that have `flex-basis: 200px` and `flex-grow: 1`. One could think that with identical markup, content and styles, they'd look the same, and yet the third one is twice bigger than the rest. Why?
 
To illustrate the children's `flex-basis`, I have added grandchildren (green) of width 200px:
 
{% codepen https://codepen.io/galoisgirl/pen/oNLmOeR %} 

Here's what happened: 

1. The browser started with the `flex-basis` and tried to fit the 200px children in lines inside the 500px parent. 
2. Two children fit in the first line, and the third one went to the second line. 
3. Once this was done, `flex-grow` was applied:
  1. In the first line, 100px were equally distributed: 50px went to each child. 
  1. In the second line, there were 300px left to distribute among only one child.

### `Flex-wrap` and `flex-shrink`

Since items that don't fit in the current line are pushed to the next one, does `flex-shrink` apply at all? I'll leave this one as a question for the reader.

### `Flex-wrap` and `flex-direction: column`

In this case, items will be laid out in columns. This [MDN article](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Mastering_Wrapping_of_Flex_Items) has an example:

![Layout with flex-wrap and flex-direction: column](https://i.imgur.com/Ufw4IFN.jpg)

For a deeper understanding of `flex-wrap`, [here's a good article](https://mastery.games/post/flex-wrap/).

## `Justify-content`, `align-items`, `align-content`

The excellent article [A Complete Guide to Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) on CSS-Tricks explains them really well, probably better than I could. I'm leaving you in good hands.