Better Programming

Advice for programmers.

Display: Flex and the Mathematics Behind It

Tushar Tuteja
Better Programming
Published in
6 min readJul 6, 2019

--

Photo by Ricardo Gomez Angel on Unsplash

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).

Image is magnified. Ruler is shown using Firefox Ruler

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.

Code for the above layout, Parent’s width is by default 100%.

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.

All three child divs are of equal size. They increased in width to occupy the remaining space.

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.

The three shrank, and now are different in size.

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.

Sizes are 40,50, and 60 and flex-shrink values are 3,2,1 respectively.

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.

--

--