Introduction
Instead of using tricks when working with flexbox, why not take the time to learn it?
By tricks, I mean things like applying min-height
to flex items because height
doesn't work.
That's what we'll do in this post. If you've used flexbox for years but never really understood it, this post is for you.
We won't cover everything, but I want to give you the knowledge to understand how flex items are generally distributed.
Flexbox model
Container
When you set display: flex
on a container, it becomes a flex container, and its direct children become flex items. This changes the way the container and its children are laid out.
I think we should dive into the default values set to understand what happens. From there, we can dive into a couple of things to be aware of to achieve your desired layout.
When a container is set to display: flex
, the following default properties are applied to it:
flex-direction: row
: This sets the main axis to be horizontal, meaning flex items are laid out in a row from left to right.flex-wrap: nowrap
: This ensures that all flex items are laid out in a single line, and they will not wrap onto multiple lines.justify-content: flex-start
: This aligns flex items to the start of the main axis.align-items: stretch
: This stretches flex items to fill the container along the cross axis.align-content: stretch
: This property has no effect when flex-wrap is set to nowrap, but it would stretch the lines of flex items to fill the container if wrapping were allowed.
To summarize this in CSS:
.container {
display: flex;
flex-direction: row; /* Default */
flex-wrap: nowrap; /* Default */
justify-content: flex-start; /* Default */
align-items: stretch; /* Default */
align-content: stretch; /* Default */
}
Items
When elements become flex items, the following default properties are applied to them:
flex-grow: 0
: Flex items will not grow to fill the available space.flex-shrink: 1
: Flex items will shrink to fit into the container if necessary.flex-basis: auto
: The initial size of the flex items is based on their content.order: 0
: Flex items are displayed in the order they appear in the source code.
To summarize this in CSS:
.item {
flex-grow: 0; /* Default */
flex-shrink: 1; /* Default */
flex-basis: auto; /* Default */
order: 0; /* Default */
}
Main and cross axis
Main axis by default is horizontal, and cross axis is vertical. But if you set flex-direction: column
, the main axis will be vertical and the cross axis will be horizontal.
Algorithm
Base size: This is determined by the
flex-basis
property.Space distribution: This is determined by the
flex-grow
andflex-shrink
properties.If more space: If the total size of the flex items is less than the container’s main size, the remaining space and how each item will grow is based on
flex-grow
values.If less space: If the total size of the flex items is more than the container’s main size, the remaining space and how each item will shrink is based on
flex-shrink
values.
Example scenario
HTML:
<div class="container">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
</div>
CSS:
.container {
display: flex;
}
.item {
flex: 1; /* shorthand for flex-grow: 1; flex-shrink: 1; flex-basis: 0; */
}
Let's break down how this code works:
Container set to flex. Takes full width. Height is determined by the content.
Items set to
flex: 1
.flex-grow: 1
: This means the items will grow equally to fill the container. But only if the items together take up less than the container.flex-shrink: 1
: This means the items will shrink equally to fit the container. But only if the items together take up more than the container.flex-basis: 0
: Basis is the initial size. I like to think of it as "What's the minimum size the item can shrink to?".
If you don't understand this, take some time to play around with the code yourself and understand.
Let's talk about modifying the different values above.
Flex grow
<div class="container">
<div class="item-1">Item 1</div>
<div class="item-2">Item 2</div>
<div class="item-3">Item 3</div>
</div>
.item-1 {
flex-grow: 1;
}
.item-2 {
flex-grow: 1;
}
.item-3 {
flex-grow: 2;
}
What's happening here?
.item-3
will take up twice as much space as .item-2
and .item-1
.
Because flex-basis
is set to 0
, the items can shrink to 0px
width.
In this case, .item-3
will take 50% of the width and .item-2
and .item-1
will each take 25% of the width.
Flex shrink
Shrink works in a similar way.
.item-1 {
flex-shrink: 1;
}
.item-2 {
flex-shrink: 1;
}
.item-3 {
flex-shrink: 2;
}
If the items together take up more than the container, .item-3
will shrink twice as much as .item-2
and .item-1
. In simpler words: .item-3
would become much smaller quicker than .item-2
and .item-1
.
Flex basis
This is one of the most confusing parts of flexbox. I used to be afraid of this because I never really understood it.
Let's take one of the items and look at different examples:
.item-1 {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 1;
}
Here we got grow and shrink set to 1. This means the item will grow and shrink to fill the container.
flex-basis
is set to 100px. This is where it gets interesting. If the item was to shrink, it can shrink to less than 100px. Basis is the initial size, and not the minimum size. So it's ok for it to shrink to less than 100px.
.item-1 {
flex-basis: 100px;
flex-grow: 1;
flex-shrink: 0;
}
Now, we set shrink to 0. This means the item is either 100px or more if there's more space. It won't shrink to less than 100px because shrink is off.
.item-1 {
flex-basis: 100px;
flex-grow: 0;
flex-shrink: 1;
}
As you might have expected, the size is 100px or less. Grow is 0. The item won't grow to fill the container. The container could possibly have space left over.
.item-1 {
flex-basis: 100px;
flex-grow: 0;
flex-shrink: 0;
}
If you set both grow and shrink to 0, the item will neither grow nor shrink. It will be 100px. This is like setting a fixed width or height. If the container has direction set to row, it'd be width, otherwise it'd be height.
Conclusion
You don't need and often shouldn't use min-height
or min-width
for flex items.
Flexbox is a powerful model for laying out items.
By understanding flex-basis
, flex-grow
, flex-shrink
and flex
, you can achieve all your layout needs.