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.

1
2
3
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.

1
2
3
flex-direction: column
1
2
3
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.

1
2
3
4
5
6
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}
1
2
3
4
5
6
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}
1
2
3
4
5
6
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:

1
2
3
4
5
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.
startAlign elements to the start of the perpendicular axis e.g. to the top (row) or left (column).
endAlign elements to the end of the perpendicular axis e.g. to the bottom (row) or right (column).
centerCenter 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,

1
2
3
4
5
align-items: stretch
1
2
3
4
5
align-items: start
1
2
3
4
5
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:

1
2
3
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).
endPlace 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).
centerDistribute whitespace evenly between the start and end of the container.
space-betweenDistribute whitespace evenly between each element.
space-evenlyDistribute 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,

1
2
3
justify-content: start
1
2
3
justify-content: end
1
2
3
justify-content: space-between
1
2
3
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}

Shopping list:

  • Roma tomatoes
  • Sourdough bread
  • 13.75mm (1/2") ThunderHex 0.875" OD x 0.280" WD Flanged Bearing
  • Mozzarella balls
  • and just about anything in between.