Flexbox is great and makes centering things easy, and that’s mostly what I’ve ever used it for. However, when I want more complex layout arrangement I find myself just searching for answers on stack overflow without actually learning how to do it. I decided to make an attempt to understand flexbox properly and share my findings in this post.
This post uses the following style for the examples:
.container {
border: 1px solid #c3c3c3;
display: flex;
flex-direction: row;
}
.container div {
width: 60px;
height: 60px;
}
The main concepts
A flex line has a direction and contains flex items. In the following example, imagine the flex line as the horizontal line going from left to right outlined by the top edge of the 3 boxes.
<div class="container" style="width: 200px; height: 80px">
<div style="background-color:coral;"></div>
<div style="background-color:lightblue;"></div>
<div style="background-color:pink;"></div>
</div>
An overflow case
When we have more items than the flex line has space for, we can specify wrapping behaviour.
If we don’t specify any wrapping, then it will override the width of the items if the parent width is fixed:
<div class="container" style="width: 200px; height: 80px; ">
<div style="background-color:coral;"></div>
<div style="background-color:lightblue;"></div>
<div style="background-color:pink;"></div>
<div style="background-color:purple;"></div>
</div>
An example where the container has no space but we set wrap:
<div class="container" style="width: 200px; height: 80px; flex-wrap: wrap">
<div style="background-color:coral;"></div>
<div style="background-color:lightblue;"></div>
<div style="background-color:pink;"></div>
<div style="background-color:purple;"></div>
</div>
When the container has sufficient space:
<div class="container" style="width: 200px; height: 160px; flex-wrap: wrap">
<div style="background-color:coral;"></div>
<div style="background-color:lightblue;"></div>
<div style="background-color:pink;"></div>
<div style="background-color:purple;"></div>
</div>
Imagine that there are two [flex] lines (or rows) containing 3 boxes and 1 box respectively.
Justify content
Justify content affects where items are along the flex direction.
By default the flex direction is row
. To make it appear in the middle of the flex lines, we can use justify-content:center
<div class="container" style="width: 200px; height: 160px; flex-wrap: wrap; justify-content: center">
<div style="background-color:coral;"></div>
<div style="background-color:lightblue;"></div>
<div style="background-color:pink;"></div>
<div style="background-color:purple;"></div>
</div>
Align items
Align item affects the placement of items within a flex line in the orthogonal axis. ie if the flex direction is “row”, it affects the vertical alignment of the items; if the flex direction is “column”, it affects the horizontal alignment.
<div class="container" style="width: 200px; height: 160px; flex-wrap: wrap; align-items: center">
<div style="background-color:coral;"></div>
<div style="background-color:lightblue;"></div>
<div style="background-color:pink;"></div>
<div style="background-color:purple;"></div>
</div>
Align content
Extending the concept of aligning items within a flex line, we can align flex lines with align content. Implicitly, it only makes sense to talk about this if we have more than one flex line, achievable using flex-wrap: wrap;
<div class="container" style="width: 200px; height: 160px; flex-wrap: wrap; align-content: center">
<div style="background-color:coral;"></div>
<div style="background-color:lightblue;"></div>
<div style="background-color:pink;"></div>
<div style="background-color:purple;"></div>
</div>
Closing remark
One practical pattern I have found for this is to have a flex container that has exactly two components and with justify-content: space-between
. This makes it easy to design lists where the content starts from the left while the action icons start on the right.