Three items in a flex row all have flex-grow: 1 but different amounts of text, and they end up unequal widths. How does flex-grow actually distribute space, and what would make them equal?
answer
- Grow divides the remainder, not the whole
- Base sizes survive into the final layout
- Zero the basis to equalise
- Factors are ratios of the free space
- Sub-one factor sums leave space unused
basics
~20 sflex-grow shares only the leftover free space, not the whole container. With flex-basis: auto each item starts at its content width and then adds an equal slice of the remainder, so they stay unequal. Use flex: 1, which sets flex-basis to 0, for equal widths.
solid answer
~50 s`flex-grow` never divides the container — it divides the **free space** that is left after every item's base size is accounted for. With `flex-grow: 1` and the default `flex-basis: auto`, each item starts at its content width, the leftover is split into equal slices, and each item gets its content width *plus* one slice, so a wordier item stays wider. The fix is `flex: 1`, which expands to `1 1 0%`: with every base size at zero, the entire container becomes free space and equal grow factors produce equal widths. The factors are proportions, so `flex: 1` and `flex: 2` in a 600px row give 200px and 400px. One extra rule worth knowing: if the grow factors across the line sum to less than 1, only that fraction of the free space is distributed and the rest stays empty.
code
css · 7 lines.row { display: flex; width: 900px; }
/* content widths 100px / 200px / 300px, free space 300px */
.row.unequal > * { flex-grow: 1; } /* -> 200px / 300px / 400px */
/* every base size is 0, so free space is the full 900px */
.row.equal > * { flex: 1; } /* -> 300px / 300px / 300px */go deeper
Know the practical rule: use flex: 1 when you want equal columns, and expect flex-grow: 1 on its own to leave wordier items wider. Be able to point at flex-basis as the reason.
Do the arithmetic out loud — subtract the base sizes from the container to get free space, then split it by the factors. Explain the ratio behaviour of flex: 1 versus flex: 2.
Diagnose the near misses: padding under content-box, a max-width capping one item and redistributing its space, or a non-flexible sibling changing the free-space budget. Say when you would move the layout to grid instead.
Own the choice of sizing model across a component library — flex distribution is per line and content-aware, grid tracks are shared across rows — and set the box-sizing and spacing conventions that stop equal-column bugs recurring.
## The algorithm in four steps For each flex line, the browser: 1. Computes each item's **flex base size** from `flex-basis` (with `auto` deferring to `width`/`height`, then to content). 2. Clamps each base by the item's own min and max constraints to get its **hypothetical main size**. 3. Computes **free space** = the container's inner main size − the sum of those hypothetical sizes (plus any `gap`). 4. If free space is positive, distributes it in proportion to `flex-grow`; if negative, distributes the deficit in proportion to `flex-shrink` scaled by base size. Step 3 is the one that answers the question. `flex-grow` operates on the *remainder*, never on the whole container, so whatever differences existed in the base sizes survive into the final layout. ## The worked example A 900px row with three items whose content widths are 100px, 200px and 300px, all `flex-grow: 1`, `flex-basis: auto`: - Sum of base sizes = 600px. - Free space = 900 − 600 = 300px. - Three equal grow factors → each gets 100px. - Final: **200px, 300px, 400px** — still unequal, just less unequal than before. Now change one declaration to `flex: 1`, i.e. `1 1 0%`: - Sum of base sizes = 0. - Free space = 900px. - Each item gets 300px. - Final: **300px, 300px, 300px** — genuinely equal. ```css .unequal > * { flex-grow: 1; } /* content size + equal share of leftover */ .equal > * { flex: 1; } /* base 0, so equal shares of everything */ ``` That single difference — basis `auto` versus basis `0` — is the whole answer, and it is why `flex: 1` became the equal-columns idiom. ## Factors are ratios, not units Grow factors are weights, compared against the sum of all factors on the line. With `flex: 1` and `flex: 2` in a 600px row, the total is 3, so the items take 1/3 and 2/3 → 200px and 400px. With bases that are *not* zero, the same ratio applies to the leftover only: two items with 100px bases in a 400px row have 200px free, so factors 1 and 3 add 50px and 150px, giving 150px and 250px — not a 1:3 ratio overall. This is also where `fr` in CSS Grid differs: an `fr` track distributes space with a min-content floor built into `minmax(auto, 1fr)`, while a flex item's floor comes from its own min constraints. Reasoning about them as "the same thing" produces wrong predictions. ## The sub-one rule The specification has a rule most people never meet: if the sum of the flex factors on a line is **less than 1**, only that fraction of the free space is distributed. A single item with `flex-grow: 0.5` and 400px of free space grows by 200px and leaves 200px empty. Once the factors sum to 1 or more, all free space is used. Fractional factors below 1 are legal and occasionally useful for "grow, but only a bit". ## Why equal factors can still give unequal boxes Even with `flex: 1` on everything, items sometimes come out different widths. The usual causes: - **Padding and border under `content-box`.** `flex-basis: 0` is a *content* base of zero, so each item's padding and border are added on top. Two items with 20px and 40px of horizontal padding will differ by 40px. `box-sizing: border-box` removes this. - **A min or max constraint.** `max-width` caps an item's growth, and the space it declined is redistributed to the others; a `min-width` floors one and takes space away. - **An item that is not actually flexible.** `flex: none` or `flex-shrink: 0` on one child changes the free space everyone else divides. ## Answering it out loud The crisp version is: "`flex-grow` splits leftover space, not the container. With `flex-basis: auto` the items start at their content sizes, so equal grow factors keep them unequal. `flex: 1` sets the basis to `0`, which makes the whole container leftover space and the items equal — assuming matching padding under `border-box`." If the interviewer pushes, do the arithmetic on a concrete container width; showing the free-space subtraction is what demonstrates you know the algorithm rather than the idiom.
- Two items have flex: 1 and identical content, yet one renders wider. What would you check first?Padding and border under `box-sizing: content-box`: `flex-basis: 0` zeroes the *content* box only, so extra padding is added on top of the equal share. After that, check for a `min-width` or `max-width` clamping one item, and for a sibling that is not flexible (`flex: none`) changing how much free space the others divide.
- What happens if the flex-grow factors on a line add up to less than 1?Only that fraction of the free space is distributed. One item with `flex-grow: 0.25` and 400px of free space grows by 100px and the remaining 300px is left unfilled. It is a deliberate spec rule that lets you say "absorb part of the slack"; once the factors reach 1 in total, all free space is consumed.
- Is flex: 1 on a flex item equivalent to a 1fr grid track?They are close but not identical. Both distribute leftover space proportionally, but a `1fr` track is `minmax(auto, 1fr)`, so it has a min-content floor built in, and grid sizes tracks across the whole container including items in other rows. A flex item's floor comes from its own min constraints, and sizing is per flex line.
Think of a bonus pool: flex-basis is each person's existing salary and flex-grow is their share of the bonus. Equal bonuses do not make unequal salaries equal — you have to zero the salaries first.
saying these in an interview costs you the question
- Says flex-grow divides the whole container width
- Thinks equal flex-grow always yields equal widths
- Believes flex-grow: 2 makes an item twice as wide overall
- Treats flex-grow as a percentage of the container
- Ignores padding when explaining unequal flex: 1 items