Display: Flex and the Mathematics Behind It
Understanding Flexbox in greater depth
Since display: flex
has arrived, coding layouts using CSS have been a breeze. One of the tricky things to understand has always been how flex-grow
and flex-shrink
work. What is the underlying mathematics behind them? This is my attempt to simplify them.
Part 1. Introduction
We’ll start with a basic page, a parent div, containing three div elements: one, two, and three respectively. One, two, and three have a height of 100px and width 50px. Look at the following picture (the code will follow).
As we can see, we have a parent div and three child divs with the colours Red, Blue, and Green respectively. The parent div has the colour Yellow.
The above file will form the basis of our article going forward. I will only be displaying layouts and corresponding CSS. The rest of the code will remain the same.
Part 2. flex-grow
Let’s give a property of flex-grow
1 to each of the child divs.
The layout looks like the following. As expected, all three divs have grown equally, dividing among them the space that was left in the parent div.
In the next example, let’s give values 1, 2, and 3 to Red, Blue, and Green respectively.
As we can see, all three grew by a different amount. Their sizes are:
- Red: 104.5 (grew by 54.5)
- Blue: 159 (grew by 109)
- Green: 213.5 (grew by 163.5)
- Parent size: 477 (free space occupied using
flex-grow
is 227)
As we can see, the space that was available to the child divs is proportionally divided in accordance with the flex-grow
value.
- Red : 277 * (1/6) = 54.5
- Blue : 277 * (2/6) = 109
- Green : 277 * (3/6) = 163.5
Note: Your values will be different depending upon your screen size. Default flex-grow
is zero.
The formula for flex-grow
is:
Space Available * (flex-grow
value of a child / sum of all the flex-grow
values)
Part 3. flex-shrink
Let’s do something interesting and make the width value of the parent 100px. That will make the parent’s value 50px less than the total value of its children.
As we can see, all three children shrank in size. They all are now of size 33.33. The default value of flex-shrink
is 1. Since there was no space available, they shrank to release 50px in space.
Let’s make the flex-shrink
value 1,2, and 3, respectively, for children.
As we can see, all three shrank and are of different sizes now. Red has the least value of flex-shrink
(shrank the least), and Green has the highest flex-shrink
value (shrank the most).
Let’s look at their sizes.
- Red: 41.6667 (shrank by 8.3333)
- Blue: 33.3333 (shrank by 16.6667)
- Green: 25 (shrank by 25)
- Parent size: 100px (children have to free up 50px in space)
As we can see, the amount of space that the children freed is in proportion to their flex-shrink
value: Red has the least, so it shrank the least, and Green has the highest and shrank the most.
- Red : 50 * (1/6) = 8.3333
- Blue: 50 * (2/6) = 16.6667
- Green: 50 * (3/6) = 25
The formula of size reduction is:
Space to Be Freed * (flex-shrink
value of a child / sum of all the flex-shrink
values)
What makes it interesting is if the size of all three children is different. Let’s make them 40, 50, and 60 respectively.
It’s hard to observe in this image, but we can see that the Green child shrank less than 25px, as earlier was the case. Let’s look at their sizes.
- Red: 26.6667 (shrank by 13.3333)
- Blue: 33.3333 (shrank by 16.6667)
- Green: 40 (shrank by 20)
As we can see, all three have the same flex-shrink
values, but all shrank by different values. It’s easy to observe that they shrank in proportion to their size. Red shrank the least, as it was the smallest, and Green shrank the most because it was the largest.
- Red : 50 * (40/150) = 13.3333
- Blue: 50 * (50/150) = 16.6667
- Green: 50 * (60/150) = 20
Now let’s change their flex-shrink
values to 3,2, and 1, just to make things little more interesting, and converge them to the final formula.
Let’s look at their sizes.
- Red: 18.5667 (shrank by 21.4333)
- Blue: 32.15 (shrank by 17.85)
- Green: 49.2833 (shrank by 10.7167)
All three shrank in proportion to their sizes and their flex-shrink
values. The formula comes out to be a little different this time. They shrank in proportion to the multiple of the flex-shrink
value and its size.
Multiples come out to be 40 * 3 for Red, 50 * 2 for Blue and 60 * 1 for Green.
- Red : 50 * (120/280) = 21.43333
- Blue: 50 * (100/280) = 17.85
- Green: 50 * (60/280) = 10.7167
The formula for flex-shrink
is
Total space to be reduced * [flex-shrink
value * initial width / Sum of (flex-shrink
value * initial value) of all the elements]
Part 4. Some More Examples
flex-shrink
values are 0,0,1 respectively. Red and Blue didn’t shrink, Green was no more(sad!)flex-shrink
values are 0,0,0 respectively. None shrank.Part 5. flex-direction and flex-basis
In the above example, everything was computed in width. That’s because, by default, the primary axis was horizontal as flex-direction
was row. If flex-direction
is column, the primary axis becomes vertical, and flex-grow
and flex-shrink
change the height of the element and not the width of the element.
Let’s see an example. Parent height is 300px and flex-direction
is column. Red, Blue, and Green have 50px height respectively.
If I add flex-grow
properties to the children, they’ll grow in the vertical direction as flex-direction
is column.
flex-grow
is 1,1,1 flex-direction
is column.Flex-basis
is the initial length of either width or height, depending upon the flex-direction
. For row, it’s width. For column, it’s height.
The shorthand to write flex properties is
flex: 1 1 100; # flex-grow flex-shrink flex-basis
There are four more properties that can be used on a child. They are min-width
, max-width
, min-height
, and max-height
. The child element will remain bounded in these four.
The child element automatically is assigned a display property flex-item
.
Part 6. Conclusion
I hope you enjoyed this article and that it was simple enough to follow. If you have any queries, please leave a comment.