CSS Flexbox: Stop Fighting Your Layouts · 第 4 / 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. 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.

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

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

Exercises

Exercise 1 · Level 1 (warm-up)

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.

Done criteria · checked locally
Exercise 2 · Level 2 (advanced)

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.

Done criteria · checked locally