CSS Flexbox: axes, alignment, and flexible sizing · Lesson 4 of 5

Lesson 04: Sharing the leftover space

Lesson objectives:

  • Explain what flex-basis, flex-grow, and flex-shrink each control.
  • Predict how flex-grow divides the free space (not the total width).
  • Read the flex shorthand and know what flex: 1 expands to.

Prerequisites: Lessons 01-03 (axes, justify-content, align-items, flex-direction) | Previous << 03 | Next 05 >>

"flex: 2 should be twice as wide" — and why it usually isn't

Sooner or later you write flex: 1 on one item and flex: 2 on another and expect the second to be exactly twice the width. Sometimes it looks right; often it doesn't, and you can't tell why. The reason is that these properties do not divide the item widths — they divide the leftover space the items don't already need. Miss that one word, "leftover," and every ratio you set feels random. This lesson pins down what actually gets divided.

Explanation

Three properties control how a flex item is sized along the main axis. Take them one at a time.

flex-basis is the item's starting size before any free space is handed out1. Think of it as "how big do I want to be before we negotiate." With the default auto, the basis comes from the item's own width or its content.

flex-grow is a grow factor: it decides how much of the positive free space an item takes when there is extra room1. The mechanism is a ratio, not a width. The browser adds up every item's grow factor, divides the free space by that total, and hands each item its share1. So flex-grow: 2 next to flex-grow: 1 means the first item gets two-thirds of the free space — not two-thirds of the container.

flex-shrink is the mirror image: a shrink factor for when items are too big and there is negative free space to remove1. Higher shrink means "give up more width when we're over budget." One subtlety that makes shrinking feel unpredictable: the amount removed is weighted by each item's base size, so with equal shrink factors a wider item gives up more width than a narrower one1.

That word "free space" is the whole lesson. Free space is what's left after every item's base size is reserved. Grow and shrink only ever act on that leftover.

You rarely set these three separately. The flex shorthand combines them: flex: 2 1 auto means flex-grow: 2, flex-shrink: 1, flex-basis: auto, and the guides recommend using the shorthand over the individual properties2. Read the flex shorthand left to right as grow, shrink, basis, and it stops being a magic number. The common one-liner flex: 1 expands to flex: 1 1 0 — grow 1, shrink 1, basis 0. Because the basis is 0, every item starts from zero and the entire row becomes free space, so flex: 1 on several items makes them genuinely equal-width regardless of content1.

The nav below has a logo, a search box, and a button. Right now the search box is only as wide as its placeholder. Make it grow to fill the empty middle, while the logo and button keep their natural size.

Only the search box got a grow factor, so only it claims the free space. The logo and button have grow 0, so they stay exactly as big as their content needs. That is the everyday "one flexible element, some fixed ones" nav pattern.

Free space has a sign, and the two directions are not symmetric

The word "leftover" hides a distinction worth naming. A container has positive free space when it is bigger than it needs to display its items — a 500px row holding three 100px items has 200px of positive free space1. It has negative free space when the combined natural size of the items exceeds the container: those same three items at 200px each total 600px in a 500px row, which is 100px of negative free space1. flex-grow only acts on the positive kind; flex-shrink only acts on the negative kind. If nothing happens when you set a grow factor, the usual reason is that there was no positive free space to hand out.

Now the asymmetry. Growing divides free space by the factors alone. Shrinking multiplies each item's flex shrink factor by its flex base size before distributing, which spreads the removal in proportion to how much each item has to give — so a small item will not shrink to nothing before a larger one has visibly narrowed1. On top of that, an item will not shrink below its min-content size, the smallest it can be while still fitting its longest word1. Those two rules together are why flex-shrink behaves less predictably than flex-grow, and they are also why shrinking rarely destroys your content.

The natural size an item starts from has a vocabulary of its own. min-content is roughly the smallest size an element can be while still fitting its longest word; max-content is the size it would need to fit all its content without wrapping1. When flex-basis is auto and the item has no width set, the basis resolves to the item's max-content size1 — which is exactly why three cards with different amounts of text start at different widths.

Reading the predefined flex values

Beyond flex: 1, four named forms show up constantly in real stylesheets, and each is just a triple in disguise3:

  • flex: initial is 0 1 auto — the item will not grow past its basis, but can shrink rather than overflow. This is the behavior you already get without writing anything.
  • flex: auto is 1 1 auto — like initial, except the item may also grow to fill the container.
  • flex: none is 0 0 auto — a fully inflexible item: it neither grows nor shrinks, which is the correct way to say "this sidebar stays 240px."
  • flex: <number> is <number> 1 0 — the basis of 0 is the whole point, and it is why flex: 1 items come out equal regardless of content3.

Note that the grow and shrink values are proportions, not units. Setting 1 and 2 gives the same result as 10 and 20, or .25 and .5 — only the ratio between siblings matters3.

Worked example (follow along)

A three-column layout where the middle column is twice as flexible as the sides:

Because all three use flex-basis: 0, the whole width is free space, split by grow factors 1 : 2 : 1. Total factor is 4, so each .side gets one-quarter of the width and .main gets one-half. Here flex: 2 really does mean "twice a side" — but only because the basis is 0, which turns the entire row into free space. Change the basis to auto and the ratio would apply to leftover space instead.

Your turn (faded example)

You want a sidebar fixed at 240px and a content area that soaks up everything else. Fill in the two flex shorthands:

Answer: .sidebar { flex: 0 0 240px; } (grow 0, shrink 0, basis 240px — it stays put) and .content { flex: 1; } (grow 1, so it absorbs all the free space). Read each shorthand as "grow / shrink / basis," and the intent is obvious: the sidebar refuses to flex, the content takes what's left.

Summary + what's next

flex-basis sets an item's starting size; flex-grow and flex-shrink divide the positive or negative free space in proportion to their factors; and the flex shorthand bundles all three, with flex: 1 meaning 1 1 0. Everything so far assumed one line of items. In the final lesson we let items wrap onto multiple rows with flex-wrap and space them with gap, then you build a real, responsive nav and card row from scratch.

Footnotes

  1. MDN: Controlling ratios of flex items along the main axis — https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Flexible_box_layout/Controlling_flex_item_ratios 2 3 4 5 6 7 8 9 10 11 12

  2. CSS-Tricks: A Complete Guide to Flexbox — https://css-tricks.com/snippets/css/a-guide-to-flexbox/

  3. MDN: Basic concepts of flexbox — https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Flexible_box_layout/Basic_concepts 2 3

Exercises

01

In your own file, build a display: flex row with two children. Give one flex-grow: 1 and leave the other at its default. Reload and see which one absorbs the empty space. Then give both flex-grow: 1.

Level 1 (warm-up)
Done criteria · checked locally
02

Set two items to flex: 1 1 200px and flex: 3 1 200px inside a row wider than 400px. Predict each final width before reloading, then measure in devtools.

Level 2 (advanced)
Done criteria · checked locally

My note

Jot down thoughts, sticking points, things you didn't get. Written to this course's appendix only — the lesson file is never touched.