Flex Basis, Grow, and Shrink

A more detailed look

Alex Tavares
hurb.labs
8 min readOct 17, 2022

--

Photo by La-Rel Easter on Unsplash

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 heightproperties of the element.

When it’s not auto, flex-basiswill 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.

Flex's main axis 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.

Flex's main axis when flex-direction is set to column

Check below for an example where every element is set to a fixed width:

How it will be rendered:

Container width: 500px

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:

Container width: 500px

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:

Container width: 500px

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:

Container width: 500px

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:

Container width: 500px

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:

Container width: 500px

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:

Container width: 500px

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:

Container width: 500px

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:

Container width: 500px

If we set flex-grow to 1 on each element, then each element will have a different width:

How it will be rendered:

Container width: 500px

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:

Container width: 500px

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 widthwhen 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:

Container current width: 300px

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:

Container current width: 200px

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:

Container current width: 200px

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:

Container current width: 600px

If we resize the container, removing 100px from it, it will have the following result:

How it will be rendered:

Container current width: 500px

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:

Scaled Shrink Factor Calculation Table

For each element, we can find their shrink ratio by dividing their scaled shrink factor by the sum of all the scaled shrink factors:

Shrink Ratio Calculation Table

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:

Element Lost Width Calculation Table

Let's depict another scenario, setting flex-shrinkto 2 on C:

How it will be rendered:

Container current width: 500px
Scaled Shrink Factor Calculation Table
Shrink Ratio Calculation Table
Element Lost Width Calculation Table

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:

--

--