Growing flex items
Growing happens separately in each flex line
Flex items grow completely separately in each flex line. This means that if flex items end up collected into separate flex lines, they have absolutely no way to affect each other’s sizing anymore.
By default, you’ll have just one flex line because flex containers don’t allow flex items to wrap. But if they do, you’ll have one or more flex lines.
There needs to be some unused space in the flex line for the flex items to grow into. By default, flex items don’t grow even if there is unused space. That’s because the initial value of flex-grow
is 0
.
Flex items never grow beyond their maximum size.
The maximum size is none
by default, which means there’s no limit to the growing. You can set this maximum size with max-inline-size
, max-block-size
, max-width
, or max-height
, whichever corresponds to the main direction of the flex container.
The minimum size “wins” over the maximum size if it’s bigger. That’s because the max size is applied first, and the min size is applied second.
Flex items grow from their flex base size, not from zero.
The flex base size is the “desired size” flex items request with flex-basis
.
If you want to ensure you end up with sizes that are exactly proportional to their flex-grow
values, then you must make sure all flex items have the same flex base size. For example, you can set flex-basis: 0
on all flex items.
When you use the flex
shorthand instead of setting flex-grow
directly, that’s exactly what happens. For example, setting flex: 1
and flex: 2
is equivalent to setting flex: 1 1 0
and flex: 2 1 0
.
Growing is exactly proportional to flex-grow
.
Unlike in shrinking, flex items grow proportionally to their flex-grow
factor. That is, the flex base size of any flex item doesn’t directly affect how much the flex items will grow.
For example, if you have two flex items with flex-grow
of 1
and 2
, then the flex item with flex-grow: 2
will always grow by twice as many pixels as the flex item with flex-grow: 1
.
Growing happens in rounds
Just like shrinking, the growing happens in rounds. Say you have 400 pixels of unused space, and you ask the two flex items to grow.
Both flex items agree, and they’re offered to grow by the same amount of 200 pixels. But one of the flex items has a maximum size set, and only grows by 100 pixels.
This means the flex container still has 100 pixels of unused space. It will start another round of growing and ask the other flex item if it wants to grow some more.
Padding and border prevent exactly proportional sizing
Let’s say you have two flex items. You want one of them to be twice as big as the other one, regardless of their content.
You set flex: 1
on the first flex item, and flex: 2
on the other flex item. This is equivalent to setting flex: 1 1 0
and flex: 2 1 0
. flex: 2 1 0
is equivalent to separately setting flex-grow: 2
, flex-shrink: 1
, and flex-basis: 0
.
flex-basis: 0
is important here. It means that both flex items will ask for “0 pixels”. Of course, that means the flex container will have unused space and it will ask the flex items if they want to grow. The flex items will then grow proportionally to their flex-grow
values of 1
and 2
.
Both flex items have some padding. We want to make sure that flex-basis
sizes the border box, not the content box, so that the final size of the flex items is proportional in spite of the padding.
The problem is, the browsers didn’t implement Flexbox in this way. Instead of growing from the flex-basis: 0
we specified, the flex items will grow from that zero plus any padding and border that are set. If you have padding: 20px
, for example, both flex items will grow from a size of 40 pixels (padding on both sides). And you will end up with flex item sizes that are not exactly proportional to their flex-grow
values.