Percentages
The two challenges of working with percentages
Using percentages can be a great way to create layouts where the size of a box depends on the size of its parent.
But, using percentages can also be confusing and frustrating. Sometimes you’ll set something like block-size: 50%
, but the resulting layout will look totally different from what you intended.
There are two challenges when it comes to working with percentages. First, when we set a percentage, what is it a percentage of? Second, why is the percentage not always applied as intended?
Most percentages refer to the corresponding size of the flex container’s content box
This includes all sizing properties: flex-basis
, inline-size
, block-size
, min-inline-size
, max-inline-size
, and so on. It also includes percentage gaps like gap: 10%
or column-gap: 10%
.
“Corresponding size” means the size of the flex container’s content box in the same axis as whatever you’re setting. If you set flex-basis: 10%
and the main axis is horizontal, then that 10%
refers to the width of the flex container’s content box.
Padding and margin percentages always refer to the inline size of the flex container’s content box
Yep, that’s pretty weird. But it’s true that if you set padding-block-end: 20%
, that 20%
will refer to the inline size of the flex container’s content box. That’s right, the all resolve against the inline size, not the size in the corresponding dimension.
I don’t think there’s a particularly great reason for doing it this way. It seems this was done to fit with how older layout types like Flow layout work.
Percentages referring to the inline size will always work
That’s because the flex container will always have a definite inline size, so the percentage can be calculated.
Inline size percentages will resolve even if your flex item’s writing mode is different and its inline size corresponds to the block size of the flex container.
That’s because if the block size of the flex container is indefinite, a fallback size will be used to calculate the percentage.
The spec outlines a few fallbacks, but browsers seem to use the size of the initial containing block in that dimension as the fallback size.
Stretched flex items let their content resolve percentages, too
The cross size of a stretched flex item is considered definite regardless of whether or not the flex container has a definite size. You could have a multi-line flex container and the percentages inside stretched flex items will still resolve.
If the size of the flex container depends on its contents, then percentages won’t work
Say your flex item has block-size: 50%
. It asks the flex container for the size of its content box. The flex container replies it needs to know the size of the flex item before it can answer. This is a chicken and egg problem.
What ends up happening is the flex item tells the flex container the size of its content so that the flex container can size itself. And instead of that percentage size, the flex item will size itself based on its content, too.