TECH
Your Ultimate Guide to CSS Flexbox
Flexbox is an essential tool to setup any layout in your application. It can be a list of things, a set of thumbnails or even a basic navigation bar. Flexbox can help placing things and making them responsive a lot easier, as it defines how your elements grow or shrink by utilizing free space.
Flex-box is a whole ecosystem of its own — but do not panic, we will get there. I will be breaking it down to parts and keep integrating new pieces as we go along.
Flex-box Model
Any component we build has a structure of a wrapper containing one or more children, and that children can again act as a wrapper to contain one or more children of its own, and so on and so forth. Every HTML DOM element follows this tree pattern.
As an example, we will be using the following tree going forward —
The grey box (a square of 500px
) is a container with three children (red, blue and green squares of 100px
). We have applied some basic styling in the basics.css
file. These styles will remain unchanged throughout the course of this article.
In a flex-box model, a wrapper (referred to as flex-container) and a child (referred to as flex-item) have different roles to play. A flex-container’s properties dictate how its children (along with the unused space) will be positioned inside of it, while the flex-item’s properties dictate whether that item has to stretch or shrink (or even take position of a sibling).
Enough with the theory now — let’s get on with it already.
Flex-container Properties
display
Syntax — display: flex
What it does— It essentially turns an element into a flex-container, and all other properties in this section has this one (display: flex
) as a prerequisite.
What just happened?
The most noticeable change is that the children gets positioned side by side, instead of stacking up (like a block element is supposed to do).
But, why?
It’s time we check out flex-direction
.
flex-direction
Syntax — flex-direction: row | row-reverse | column | column-reverse
Default— row
What it does — Flex-items are laid out in the flex-container along the axis defined in the its flex-direction.
row
— left to rightcolumn
— top to bottomrow-reverse
— right to leftcolumn-reverse
— bottom to top
If a flex-direction
is not explicitly assigned to a flex-container (i.e. any element with display: flex
), it takes the default value — row
.
But, what if content overflows?
It’s flex-wrap
to the rescue.
flex-wrap
Syntax — flex-wrap: nowrap | wrap | wrap-reverse
Default— nowrap
What it does — flex-wrap
dictates what happens when content inside a flex-container overflows.
nowrap
— content tries to fit into one line, and overflows if there are restraints.wrap
— content gets wrapped into multiple lines (as perflex-direction
).wrap-reverse
— content gets wrapped into multiple lines (opposite direction offlex-direction
).
PRO TIP —
You can useflex-flow
as a shorthand forflex-direction
andflex-wrap
.
As for example —flex-flow: row wrap;
is essentiallyflex-direction: row; flex-wrap: wrap;
Let’s increase the size of the small boxes to 200px
to create a use-case for content overflow —
What just happened?
The default flex-wrap: nowrap
is making those boxes shrink down their widths to squeeze into the container. Our boxes are no longer squares, but some weird rectangles.
However, it cannot overpower min-width
(or min-height
for flex-direction: column
), and content overflows to the right (or bottom, respectively).
But, flex-wrap: wrap
breaks them into multiple lines, while respecting element’s assigned width —
SNEAK PEEK —
Did you notice the space between the lines when the content gets wrapped?
Take a look at thealign-content
section below to understand why.
justify-content
Syntax — justify-content: flex-start | center | flex-end | space-between | space-around | space-evenly
Default — flex-start
What it does— justify-content
dictates how the flex-items are positioned along the flex-direction
provided in the flex-container.
flex-start
— items are placed at the start of the container.center
— items are placed at the center of the container.flex-end
— items are placed at the end of the container.space-between
— items are placed with equal space between them, first and last child are at the start and end of the container respectively.space-around
— items are placed with equal space around them, the space between any two adjacent item is exactly double the space between the first item (as well as the last) and its closest container boundary. This is because — the gap between first and second item contains both of their spacings, whereas it only takes the first one’s when it comes to the space between the first item and the wall.space-evenly
— items are placed in a way that the space between any two adjacent items (as well as the boundaries) are equal.
PRO TIP —
When we are placing items usingjustify-content
, we can have the unintended consequence of pushing items outside the container (when content overflows) — in a way that they can not be scrolled to (check example below). Adding asafe
keyword can be a life-saver in such cases.
align-items
Syntax — align-items: stretch | flex-start | flex-end | center | baseline
Default — stretch
What it does— align-items
dictates how the flex-items are positioned along the perpendicular of the flex-direction
provided in the flex-container.
To understand this properly, let’s unset the height of the small boxes —
What just happened?
If we do not provide any height (or width, for flex-direction: column
) to the items, they stretch to fill up the container. Luckily, we can control this default behavior by adjusting align-items
—
stretch
— items stretch to fill the container.flex-start
— items are placed at the start of the axis perpendicular to givenflex-direction
.center
— items are placed at the center of the axis perpendicular to givenflex-direction
.flex-end
— items are placed at the end of the axis perpendicular to givenflex-direction
.baseline
— items are aligned according to their baselines.
PRO TIP —
Similar tojustify-content
,safe
keyword works withalign-items
too.
align-content
Syntax — align-content: stretch | flex-start | center | flex-end | space-between | space-around | space-evenly
Default — stretch
What it does— align-content
dictates how space between the lines are used up, when content is wrapped.
Prerequisite — flex-container must have flex-wrap: wrap | wrap-reverse
, since nowrap
prevents content from moving on to the next line.
To understand this properly, let’s add flex-wrap: wrap
first and make the boxes bigger so that content overflows —
What just happened?
The lines are stretching to fill up the container (since align-content: stretch
by default), whereas the items are restricted by the height
property. If we unset the height
—
When flex-container is wrapped and the content is moved to next line, the space between the lines can be controlled by this property.
stretch
— items stretch to fill the space in between the lines.flex-start
— lines are positioned at the start of the container with no space in between.center
— lines are positioned at the center of the container with no space in between.flex-end
— lines are positioned at the end of the container with no space in between.space-between
— items are placed in a way that the lines have equal space between them, first and last line are at the start and end of the container respectively.space-around
— items are placed in a way that the lines have equal space between them, the space between any two adjacent lines is exactly double the space between the first line (as well as the last) and its closest container boundary.space-evenly
— items are placed in a way that the lines (as well as the boundaries) have equal space between them.
PRO TIPS —
#1 → Similar tojustify-content
andalign-items
,safe
keyword works withalign-content
too.
#2 → You can useplace-content
as a shorthand foralign-content
andjustify-content
.
As for example —place-content: flex-start center;
is essentiallyalign-content: flex-start; justify-content: center;
Flex-item Properties
flex-grow
Syntax — flex-grow: any positive integer
Default — 0
What it does— flex-grow
dictates how a flex-item grows if there is space available (in the given flex-direction
).
A flex-item with flex-grow: 2
tries to take up twice the unused space than a flex-item with flex-grow: 1
. This is best explained through examples —
flex-shrink
Syntax — flex-shrink: any positive integer
Default — 1
What it does— flex-shrink
dictates how a flex-item shrinks if there is no space available (in the given flex-direction
).
When there is no space available, flex-items shrink down to squeeze inside the container. flex-shrink
controls the factor by which a flex-item shrinks. A flex-item with flex-shrink: 2
tries to squeeze down by a factor twice than that of a flex-item with flex-shrink: 1
.
We are assigning a width of 400px
to the blue box, so that the other boxes shrink down to make accommodation—
PRO TIP —
If you want a flex-item to not shrink down under any circumstances, setflex-shrink: 0
.
flex-basis
Syntax — flex-basis: auto | 0 | any size value
Default — auto
What it does— flex-basis
defines the default size of the flex-item. All flex-grow
/ flex-shrink
values are factored in along with flex-basis
to reach the final size of a flex-item.
What does that even mean?flex-basis
is the final step in understanding how the size of a flex-item is calculated. Let’s dive into it by looking at some use cases —
Case 1 — equal size | equal stretch
We are unset-
ting the width, assigning flex-grow: 1
and applying flex-basis: 100px
to all the small boxes. We are essentially replacing the width
property here with flex-basis
, as well as asking them to occupy the rest of the unused space —
What just happened?
Container size = 500px
Box size before flexing — i.e. flex-basis
= 100px
Unused space = 500px — (3 * 100px)
= 200px
Total flex grow — every flex-item has flex-grow: 1
= 3
Box increases by = 200px * (1 / 3)
= 66.67px
Final box size = 100px + 66.67px
= 166.67px
Case 2 — double size | equal stretch
We are increasing the flex-basis
of the red box to 200px
. Let’s see how that changes the layout —
What just happened?
Container size = 500px
red box size before flexing — i.e. flex-basis
= 200px
(blue / green) box size before flexing — i.e. flex-basis
= 100px
Unused space = 500px — (2 * 100px) — 200px
= 100px
Total flex grow — every flex-item has flex-grow: 1
= 3
Boxes increases by = 100px * (1 / 3)
= 33.33px
Final red box size = 200px + 33.33px
= 233.33px
Final (blue / green) box size = 100px + 33.33px
= 133.33px
Case 3— double size | double stretch
We are keeping the flex-basis
of the red box at 200px
, but also increasing the flex-grow: 2
. Let’s see how that changes the layout —
What just happened?
Container size = 500px
red box size before flexing — i.e. flex-basis
= 200px
(blue / green) box size before flexing — i.e. flex-basis
= 100px
Unused space = 500px — (2 * 100px) — 200px
= 100px
Total flex grow — (blue / green) box has flex-grow: 1
, red box has flex-grow: 2
= 4
red box increases by = 100px * (2 / 4)
= 50px
(blue / green) box increases by = 100px * (1 / 4)
= 25px
Final red box size = 200px + 50px
= 250px
Final (blue / green) box size = 100px + 25px
= 125px
In a nutshell — flex-basis
controls the default size of a flex-item (width|height
for flex-direction: row|column
respectively). It can take a few other values as well —
auto
—flex-basis
takes the width (or height forflex-direction: column
) value of the flex-item.0
—flex-basis
takes the size of its content.any size value
—flex-basis
takes it as it is.
flex
Syntax — flex: initial | auto | none | one-two-three-value
Default — auto
What it does — A combination of flex-grow
, flex-shrink
and flex-basis
is all you are going to need to size a flex-item. Luckily, we have a shorthand which combines all these properties —
initial
—flex: initial
→flex-grow: 0; flex-shrink: 1; flex-basis: auto;
flex-item shrinks to fit its content, but never grows to occupy unused space, its default size is based on its assignedwidth / height
.auto
—flex: auto
→flex-grow: 1; flex-shrink: 1; flex-basis: auto;
flex-item shrinks to fit its content, and grows to occupy unused space, its default size is based on its assignedwidth / height
.none
—flex: none
→flex-grow: 0; flex-shrink: 0; flex-basis: auto;
flex-item is no longer flexible. It does not shrink or grow, its size is based on its assignedwidth / height
.- One value syntax —
flex: 1
→flex-grow: 1; flex-shrink: 1; flex-basis: 0;
- Two value syntax —
flex: 1 2
→flex-grow: 1; flex-shrink: 2; flex-basis: 0;
- Two value syntax —
flex: 1 100px
→flex-grow: 1; flex-shrink: 1; flex-basis: 100px;
- Three value syntax —
flex: 1 2 100px
→flex-grow: 1; flex-shrink: 2; flex-basis: 100px;
align-self
Syntax — align-self: auto | stretch | flex-start | flex-end | center | baseline
Default — auto
What it does — It overrides the align-items
value given to it by flex-container, for that particular flex-item.
order
Syntax — order: any number
Default — 0
What it does — It dictates which position a flex-item will take. By default, it follows the order in which they are written, but a flex-item with a higher order value is positioned after the others.
That essentially ends all the key properties you need to know to get on with flex-box. However, I have discussed a few use-cases in the section below which can help you solve some day-to-day flex problems.
FAQs
#1 — Why are there no justify-items
and justify-self
?
Flex-box model do not have justify-items
and justify-self
, because those results can be achieved by margin
property (as you will find out in examples below).
justify-content
— places items in the axis given inflex-direction
.align-content
— places items in the axis perpendicular to the one given inflex-direction
.align-items
— controls space between the lines in the axis perpendicular to the one given inflex-direction
.margin
— controls space between the lines in the axis given in flex-direction (for every flex-item).
#2 — How can I center an element (both horizontally and vertically) using flex-box?
Voila!
#3 — How can I corner an element using flex-box?
Adding a margin-left: auto
to the green box will move it to the right edge of the container —
Whereas, we can use align-self: flex-end
to move it to the bottom —
References
- A Complete Guide to Flexbox [CSS Tricks] by Chris Coyier.
- Basic_Concepts_of_Flexbox [MDN Web Docs]
BONUS TIPS —
#1 → Do check out Flexbox Froggy. It’s a fun way of learning and polishing your flex-box skills through an interactive game. Trust me, you would love it !
#2 → You can also check out this extensive course on flex-box by Wes Bos.
Fin
Thank you and congratulations on reaching the end of the article. I hope you find it useful.
While you are here, you can also check out a few of my other articles —
- 10 Modern JavaScript syntax to help you code faster
- 10 CSS things I wish I knew when I was a beginner
Cheers!