Flex(box)
Code:
1.container {
2 display: flex;
3}
Flexbox, or the "flexible box" layout in CSS, is the greatest (CSS) invention since z-index
. A flex container is easy to specify, and is useful in a huge range of CSS applications.
As always, while the examples on this page are touched-up a bit for visuals, you can always open inspect element and poke around or view this page's source code on GitHub.
display: flex
Conceptually, a flex container aligns its children along a certain axis (horizontal, by default, or vertical). This is controlled by the flex-direction
property.
Code:
1.container {
2 flex-direction: column;
3}
Flex direction can be set to row
, to set the axis to horizontal (the default), or column
, to set the axis to vertical. While less commonly used, there is also row-reverse
and column-reverse
, which function like row and column but with the order of elements reversed.
flex-direction: column
flex-direction: column-reverse
By default, a flex container will force its children to remain on its specified axis. If the children are too wide (or tall, for flex-col
), they will overflow.
If you want overflowing elements to wrap around instead, use the flex-wrap
property.
Code:
1.container {
2 flex-wrap: wrap;
3}
flex-wrap
can be set to nowrap
(the default), which forces elements onto a single row / column, or wrap
to allow wrapping.
flex-wrap: wrap
If you wanted to add even spacing between elements using margin
, you'd have to be careful to specify :not(:first-child)
so as to avoid accidentally adding left or top margin to the first element and shifting the entire container. Plus, for a wrapped flex container, calculating which elements should receive top margin is incredibly complex.
Instead, to add even spacing between elements in a flexbox, use the gap
property. gap
simplifies all the aforementioned logic into a single, concise statement:
Code:
1.container {
2 gap: 1rem;
3}
gap: 1rem
Indeed, gap
is actually a shorthand for two properties, column-gap
and row-gap
. To specify different gap widths for the x and y axes, you can set these directly:
Code:
1.container {
2 column-gap: 1rem;
3 row-gap: 0.5rem;
4}
column-gap: 1rem; row-gap: 0.5rem
Wrapping is great, but how do we deal with the excess whitespace in the container?
To align elements along the perpendicular (cross) axis of the flex container, use the align-items
property.
Code:
1.container {
2 align-items: center;
3}
To center items vertically when the flex direction is row, for example, use align-items: center
:
align-items: center
align-items
takes the following values:
stretch (default) | Stretch each element to fill the entire height or width of the container. If this is confusing, see the example below. |
start | Align elements to the start of the perpendicular axis e.g. to the top (row) or left (column). |
end | Align elements to the end of the perpendicular axis e.g. to the bottom (row) or right (column). |
center | Center elements vertically (row) or horizontally (column). |
There are some 10+ other values for align-items
, but in 99% of cases the above 4 will suffice; the curious can read about them here. For some more examples,
align-items: stretch
align-items: start
align-items: end
To align elements along the parallel (main) axis of the flex container, use the justify-content
property.
Code:
1.container {
2 justify-content: center;
3}
To center items horizontally when the flex direction is row, for example, use justify-content: center
:
justify-content: center
While it suffices to think of justify-content
as aligning elements along the container's parallel axis, what justify-content
actually controls is the distribution of whitespace within the container.
Then, justify-content
takes the following values:
start (default) | Place whitespace at the end of the container e.g. the right (row) or bottom (column); this results in elements being pushed to the left (row) or top (column). |
end | Place whitespace at the start of the container e.g. the left (row) or top (column); this results in elements being pushed to the right (row) or bottom (column). |
center | Distribute whitespace evenly between the start and end of the container. |
space-between | Distribute whitespace evenly between each element. |
space-evenly | Distribute whitespace evenly between the start and end of the container, as well as each element. |
There are also a few more values for justify-content
, but in 99% of cases the above will suffice; the curious can read about them here. For some more examples,
justify-content: start
justify-content: end
justify-content: space-between
justify-content: space-evenly
So now that you know flexbox, what can you do with it?
There's an oft-repeated joke about how centering a div proves to be a monumental task in CSS. But this joke is outdated; using flexbox, we can center a div in 3 lines of code:
Code:
1.container {
2 display: flex;
3 align-items: center;
4 justify-content: center;
5}

Some filler title ...
Some filler text ...
Indeed, flex is great for anything you need to display together in a row, like cards in a section,
Code:
1.wrapper {
2 display: flex;
3 gap: 2rem;
4 justify-content: center;
5}

Card title A ...
Some filler text ...

Card title B ...
Some filler text ...

Card title C ...
Some filler text ...
elements in a navbar,
Code:
1.nav {
2 display: flex;
3 align-items: center;
4 justify-content: space-between;
5}
6
7.nav > .right {
8 display: flex;
9 gap: 1rem;
10}
any time you have stacked elements ever,
Code:
1.list {
2 display: flex;
3 flex-direction: column;
4 gap: 0.5rem;
5}