Flex Basis, Grow, and Shrink
A more detailed look
Introduction
In this article, we'll have a more detailed look at how flex manipulates element sizes based on their flex-basis
, flex-grow
, and flex-shrink
properties.
Flex Basis
The flex-basis
property represents the initial size of a flex element. It's related to flex's main axis, and its default value is auto
.
When it’s set to auto
, it will look for the width
or height
properties of the element.
When it’s not auto
, flex-basis
will override width
or height
, depending on the flex-direction
property.
For instance, flex-basis
relates to the width
property when flex-direction
is set to row
.
In the same way, if flex-direction
is set to column
, flex-basis
relates to the height
property.
Check below for an example where every element is set to a fixed width
:
How it will be rendered:
As we can see, since flex-basis
is set to auto
by default, every element respects the width
property, but what if we want the elements to have the size of their contents? To achieve that, we can set flex-basis
to content
so that it won't consider the element's width
property.
Check below for an example where every element is set to a fixed width
(120px) and flex-basis
is set to content
:
How it will be rendered:
Other than auto
and content
, flex-basis
can receive an absolute length or a percentage of the parent flex container's main size property. Check the example below:
How it will be rendered:
Flex Grow
The flex-grow
property defines how much an element will grow, taking up from the available space of its container. It means that when you set this property to an element, this element tells flex how much from the available space of its container it is willing to take up and then add to its base size (flex-basis
).
Let's say we have the following initial scenario, where we have 3 elements (A, B, and C) with an initial basis of 100px inside a 500px width container:
How it will be rendered:
If we set flex-grow
to 1 on A, it means that A wants 1 share of the available space. Since A is the only one wanting to grow, it will take all of the available space (200px) and add up to its basis:
How it will be rendered:
Now, if we set flex-grow
to 1 on B too, both A and B want to reclaim 1 share of the available space. So from the 200px remaining, 100px will go to A and 100px will go to B:
How it will be rendered:
What happens if we set flex-grow
to 2 on B? Now B wants 2 shares of the available space, while A still wants 1. So if we divide the remaining space by 3, we have approximately 66.67px equal pieces, so we can give 1 share to A and 2 shares (133px) to B (approximate values):
How it will be rendered:
Finally, if we set flex-grow
to 1 on C, we now have 4 shares of the available space (50px each) to distribute. 1 share goes to A, 2 shares go to B and 1 share goes to C:
How it will be rendered:
Flex-basis zero
You might wonder why you would want to set flex-basis
to zero and what are the consequences of doing so. To illustrate that, let's assess a specific case.
Let's say we have all 3 elements with their default flex properties. We would have the following scenario (notice that, in this case, flex-basis: auto
will end up respecting the content's size just because we don't have a width
defined for each element):
How it will be rendered:
If we set flex-grow
to 1 on each element, then each element will have a different width
:
How it will be rendered:
As we have seen before, each element grows from its base size. If we want to make them grow evenly, we can set flex-basis: 0px
, and then all elements will grow as if they have no content at all:
How it will be rendered:
Note that setting flex-basis: 0px
won't make an element with content literally disappear on screen if flex-grow
is not set, for instance. Instead, flex will make the element have the smallest possible width and consider it 0 to calculate its new width
when it grows.
Flex Shrink
The flex-shrink
property in contrast to flex-grow
, is a property that defines how much an element will shrink to fit a container that cannot hold its size. It means that this element is telling flex how much of its size it's willing to give up to fit in the container.
Let's say we have 3 elements with a flex-basis
of 100px each inside a container that has the same size as the sum of the 3 elements (300px):
How it will be rendered:
With a container that can hold their sizes, none of the elements have to shrink to fit in.
But what happens if we resize the container, removing 100px from its width?
How it will be rendered:
As we can see, all the elements shrunk to fit in the new container width. As they have the same flex-basis
(100px) and flex-shrink
is set to 1, each element will lose approximately 33px.
If we change flex-shrink
to 2 on A, it will shrink more than the others:
How it will be rendered:
Again, since they have the same flex-basis
(100px), each element will lose a portion relative to their flex-shrink
. We now have 4 portions of the lost space (25px) to remove from the elements. A will remove 2 portions (50px). B and C will remove 1 portion each (25px).
Note that when they have the same flex-basis
, it looks like flex is removing the necessary space using the same logic it grows elements. But what happens if we have different flex-basis values? Then we will notice that there is something different going on.
How it is calculated
Now things can get a little bit more complicated. But remember that you don't need to know exactly how things work behind the scenes. It suffices to understand the effects of the property on the elements and how it will help improve your UI.
Let's say we have A with 100px of flex-basis
, B with 200px, and C with 300px, as the following:
How it will be rendered:
If we resize the container, removing 100px from it, it will have the following result:
How it will be rendered:
As we can see, it is not as straightforward as flex-grow
but let's break it down together.
First, we need to scale the flex-basis
value of each element with their respective flex-shrink
factors and also sum them:
For each element, we can find their shrink ratio by dividing their scaled shrink factor by the sum of all the scaled shrink factors:
Finally, for each element, we multiply their shrink ratio by the total lost width, and then we get the value each element will have to give up to fit its container:
Let's depict another scenario, setting flex-shrink
to 2 on C:
How it will be rendered:
Conclusion
I hope this article helped you get a better understanding of how the elements will behave depending on the flex properties we are using.
Even though it might not be trivial to understand exactly what’s happening, and most of the time I think we won’t need that, it’s nice to have a better understanding of how the elements will behave depending on the flex properties we are using.
In my opinion, the best way to grasp the concepts is by practicing. So the more we use those properties, the more we’ll know how to apply them in order to help us improve our UI.
Thanks for reading this article!
Playground
Check out below a sandbox where you can change the properties and see how the elements behave: