Basis

Misinterpreting the flex-grow value is easy to do. Consider this layout with three tiles having flex-grow values 1, 1, and 3:

html
css
preview

The weights sum to 5. That means that the first two tiles each consume 1/5 of the parent and the third consumes 3/5, right? Wrong. Try inspecting the tiles with your browser's developer tools and you will find that the third tile is not three times as wide as the other two.

But watch what happens when you don't set the width of the tiles:

html
css
preview

Try using your developer tools to inspect the widths now. You will find that the third tile is indeed three times as wide as its siblings. In this case, the misinterpretation of flex-grow as a proportion of a child within its parent happens to be right. But the correctness is accidental.

The misinterpretation is made apparent when content is added. Watch what happens when the first tile gets a paragraph of text:

html
css
preview

The first child has eaten up all the horizontal space of the parent. The second and third tiles, even though they have flex-grow values of 1 and 3, don't appear at all. This is because flex-grow only applies to the parent's leftover space, not its entire space.

In this case, there is no leftover space. The paragraph element is a block element that consumes all the available width, leaving none for the second and third tiles.

This behavior is explained by examining the formulas that the browser uses to calculate a flex child's expanded size. In a horizontal flex parent, a child's claim on the extra space is computed by applying the proportion of growth to the extra space:

$$ \textrm{extra} = \frac{\textrm{child's flex-grow}}{\textrm{total flex-grow}} \times \textrm{parent's leftover space} $$

The child's overall width is a combination of this extra space and its basis:

$$ \textrm{width} = \textrm{basis} + \textrm{extra} $$

A child's basis is the size of an element before it gets any extra space. It is set using the flex-basis property. By default, flex-basis is auto, which means the basis is set by the width (or height, for vertical containers). If you set flex-basis to 0, then the child starts with no visible area. See what happens when the bases for all tiles are set to 0:

html
css
preview

When the bases are 0, the flex-grow property does size each child as a proportion of the parent. That's because all the space in the parent is leftover space. None of it went toward satisfying a basis.

This technique of setting bases to 0 is useful when you are trying to create user interfaces that behave like the ones you see in desktop applications. However, with a basis of 0, a child may get so small that it can't be interacted with easily. You may want to also specify a child's min-width to prevent this.

The interplay between flex-grow, flex-basis, width, height, and min-width, and min-height can get a little murky. Be careful!