Section 2 · Layout That Holds Up
Flexbox in Depth
18 min3 min readCode playground
Lesson at a glance
Predict how flexbox sizes items from flex-basis, grow and shrink, fix the min-width auto overflow trap, and build rows that wrap without media queries.
- 1How flexbox decides sizes
- 2The min-width: auto trap
- 3Push with auto margins
- 4Wrapping without media queries
- 5Your turn
No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.
The session row on Waypoint’s schedule is three things in a line: a time, a title and a save button. It looks fine until the content team schedules “Shipping Accessible Design Systems Across Twelve Product Teams Without Losing Your Mind”, and the save button slides off the edge of the card. Nothing in the CSS mentions widths, so where did the overflow come from?
From flexbox doing exactly what its algorithm says. Once you know the algorithm, this bug takes thirty seconds to fix.
How flexbox decides sizes
Flexbox sizes items along the main axis in two passes:
- Hypothetical size. Each item starts at its
flex-basis. With the defaultauto, that’s itswidthif set, otherwise its content width. - Distribute the difference. The container compares the sum of the bases (plus gaps) with its own size. If there’s space left, items with
flex-growshare it in proportion to their grow factors. If there’s too little, items withflex-shrinkgive some back, weighted by shrink factor times basis, so big items shrink more.
The flex shorthand sets all three values, and its keywords are worth memorising because they behave very differently:
| Shorthand | Expands to | Use it for |
|---|---|---|
flex: 1 |
1 1 0% |
Equal columns, whatever the content |
flex: auto |
1 1 auto |
Keep content size, share only the extra |
flex: none |
0 0 auto |
Never grow or shrink (icons, buttons) |
flex: 0 0 5rem |
fixed basis | A column of exact width |
The min-width: auto trap
Back to the runaway title. It has white-space: nowrap, so its content width is the whole sentence, maybe 700px. The row is 400px. Shrinking should solve it, so why doesn’t it?
Because flex items have min-width: auto by default, and for a flex item that means “no smaller than my min-content size”. Shrinking stops at that floor. The unbreakable title can’t shrink below its full width, so it overflows and drags the button with it.
.session-row {
display: flex;
align-items: center;
gap: 12px;
}
.session-row .time { flex: 0 0 5rem; }
.session-row .title {
flex: 1;
min-width: 0; /* allow shrinking below content size */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.session-row .save { flex: none; }min-width: 0 removes the floor, and the three overflow properties turn the clipped text into a tidy ellipsis. The same trap appears with long URLs, code blocks and nested flex or grid containers, so this is a fix you’ll write many times.
Push with auto margins
Waypoint’s header holds the logo, the day switcher and a “Get tickets” link that belongs at the far end. justify-content: space-between would spread all three apart. An auto margin is more precise:
.site-header { display: flex; align-items: center; gap: 1rem; }
.site-header .tickets { margin-inline-start: auto; }Auto margins on flex items absorb all free space on their side, so the link moves to the end and everything before it stays packed together. It’s the flexbox equivalent of “and then a spring”.
Wrapping without media queries
The filter bar holds four track filters. On a wide screen they fit on one line; on a phone they shouldn’t be squeezed to unreadable slivers. Wrapping plus a basis gives you that with no breakpoint:
.filters {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.filters > * {
flex: 1 1 10rem;
}Each filter wants 10rem. The browser fits as many 10rem items as it can on a line, wraps the rest, then lets each line’s items grow to fill it. At 25rem wide you get two per line; at 45rem, all four. The breakpoint is implied by the content.
Your turn
The exercise gives you a 400px session row with a very long title. Make the time a fixed 5rem column, let the title fill the remaining space and truncate with an ellipsis, and keep the save button at the end. When rows of cards need to line up in two dimensions, flexbox runs out of road; that’s where grid takes over in the next lesson.
Key takeaways
- Flexbox sizes items in two passes: each item starts at its
flex-basis, then leftover space is shared byflex-growor a shortfall is taken back byflex-shrink. flex: 1means1 1 0%, so items get equal shares regardless of content;flex: automeans1 1 auto, so content size is kept and only the extra is shared.- Flex items default to
min-width: auto, which stops them shrinking below their content; setmin-width: 0to let text truncate instead of overflowing. - An auto margin on a flex item absorbs all free space on that side, which is the cleanest way to push one item to the far end.