The following is a guest post by Manuel Matuzovic. It illustrates how flex-grow works, weird quirks and all. Then he goes into several examples on how common layout patterns may be implemented using flex-grow and flex-basis.

When I found out about flex-grow, I made a simple demo to find out what it did and how it worked.
I thought I got everything figured out, but when I tried it on a website a colleague has recently made, nothing worked as expected. No matter what we did, the layout didn’t look and work like it did in my demo. That got me thinking and I started to doubt that I knew what flex-grow was all about.

How flex-grow doesn’t work

Before we are going to take a deep dive into the functionality of flex-grow, I want to explain to you what I got wrong at first.

I thought that all flex items with flex-grow set to 1 would have an equal width. If one of the items had flex-grow set to 2 that item would be twice as big as all the others.

This sounds great. It seems as if this is exactly what’s happening in the Pen I mentioned before. The parent element is 900px wide, the section with flex-grow: 2 has a calculated width of 600px and the aside element with flex-grow: 1 has a calculated width of 300px.

As you can see, everything works out perfectly in this demo, but it did not work at all in a real life example, even though we used the exact same CSS. As it turns out, the problem wasn’t the CSS, but the content (or lack of content). The demo I made works, because by only using two empty elements I created a test case that was too simple to depict the important specifics of the property.

How flex-grow really works

I just described how flex-grow does not work, but I showed you a demo that actually does do what I claim it does not (Later on in this article I will explain the reason for this.).

To clarify things, let me show you another Pen. We have got the exact same setup as in the first pen, but this time the section and aside elements aren’t empty. Now the ratio isn’t 2:1 anymore and the element with flex-grow set to 1 is actually bigger than the element with flex-grow set to 2.

Explanation

If we apply display: flex; to the parent element and don’t change anything else, the child elements will be stacked horizontally, no matter what. If there isn’t enough space, they will shrink in size. If on the other hand there is more than enough space, they won’t grow, because Flexbox wants us to define how much they should grow. So rather than telling the browser how wide an element should be, flex-grow determines how the remaining space is distributed amongst the flex items and how big the share is each item receives.

Or in other words:

A flex container distributes free space to its items (proportionally to their flex grow factor) to fill the containers, or shrinks them (proportionally to their flex shrink factor) to prevent overflow.

https://drafts.csswg.org/css-flexbox/#flexibility

Demonstration

The concept is much easier to understand if we visualise it.

First we set the display property of our parent element to flex and by doing that our child elements become flex items and are positioned horizontally next to each other.

Next we decide how many shares of the extra space each element receives. In our previous example the first element receives 2/3 of the remaining space (flex-grow: 2) and the second element 1/3 (flex-grow: 1). By knowing how many flex-grow values we have in total, we know by which number to divide the remaining space.

Finally we have the number of distributable pieces. Each element receives the appropriate number of pieces based on its flex-grow value.

Calculation

Theory and visual representations are nice, but let’s get dirty and do the math for the above example.

For our calculation we need 4 numbers: The parent width, the initial width of our section and our aside element and the total number of flex-grow values we’ll use.

parent width: 900px
section width: 99px
aside width: 623px
total flex-grow values: 3

1. First we have to calculate the remaining space

That’s pretty easy. We take the parents width and subtract the total initial width of every child element.

900 - 99 - 623 = 178

parent width – initial section width – initial aside width = remaining space

2. Next we have to determine how much one flex-grow is

Now that we have the remaining space we need to determine into how many slices we want to cut it. The important thing here is that we don’t divide the remaining space by the number of elements, but by the number of total flex-grow values. So in our case that’s 3 (flex-grow: 2 + flex-grow: 1)

178 / 3 = 59.33

remaining space / total flex-grow values =