CSS · Layout
Flexbox
⚡ TL;DR — Flexbox lays items out along one axis and distributes the free space left over.
flex: grow shrink basistells each item how to absorb or give up that space. The single detail that separates seniors from juniors: a flex item's defaultmin-widthisauto(its content size), which is why long text and images overflow —min-width: 0is the fix.
🧠 Mental model
Flexbox is a one-dimensional negotiation over free space. Pick a main axis (flex-direction: row or column); the cross axis is perpendicular. The algorithm:
- Lay every item out at its
flex-basis(its ideal size along the main axis). - Add up the bases. Compare to the container's size.
- Leftover space? Hand it out by
flex-growratios. - Not enough space? Take it back by
flex-shrinkratios (weighted by basis).
justify-content distributes along the main axis; align-items aligns along the cross axis. That's the whole model — everything else is refinement.
⚙️ How it actually works
The flex shorthand is three properties, and the common keywords expand to:
| Shorthand | grow / shrink / basis | Meaning |
|---|---|---|
flex: 1 |
1 1 0% |
Grow to fill, ignore content size, equal columns |
flex: auto |
1 1 auto |
Grow to fill, starting from content size |
flex: none |
0 0 auto |
Fixed at content size, never flex |
flex: 0 1 auto |
(the default) | Don't grow, do shrink |
flex: 1 uses basis 0, so items ignore their content and split space equally — that's why flex: 1 on siblings makes equal columns, while flex: auto makes columns proportional to their content.
Why items overflow — the min-width: auto trap. By spec, a flex item's min-width (in a row) defaults to auto, which computes to its min-content size — the longest unbreakable word, or an image's intrinsic width. Shrinking stops there. So a flex child holding a long URL or a <pre> block refuses to get narrower than its content and blows out of the container. The fix is to override that floor: min-width: 0 (or overflow: hidden), which lets the item shrink and its content wrap or clip. In a column, the equivalent is min-height: 0. This is the flex interview question.
align-items: stretch is the default — items grow to fill the cross axis (equal-height cards for free). align-self overrides per item. gap spaces items without margin hacks and doesn't add space at the ends.
💻 Code
.container {
display: flex;
gap: 16px; /* clean spacing, no edge margins */
align-items: stretch; /* default: equal-height children */
}
/* Equal columns vs content-proportional columns */
.equal > * { flex: 1; } /* basis 0 → all equal regardless of content */
.natural > * { flex: auto; } /* basis auto → wider content gets more space */
/* ❌ Long text / images blow out the layout */
.item { flex: 1; }
/* the text child won't shrink below its longest word → horizontal overflow */
/* ✅ Let the flex item shrink past its content size */
.item { flex: 1; min-width: 0; } /* now truncation/wrapping works */
.item p { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The classic push-apart pattern: margin-auto eats free space */
.navbar { display: flex; }
.navbar .logo { margin-right: auto; } /* pushes everything after it to the right */
/* Perfect centering in two lines */
.center { display: flex; justify-content: center; align-items: center; }
⚖️ Trade-offs
- Flex is for one dimension; Grid is for two. A toolbar, a row of cards, a stack — flex. A page layout with aligned rows and columns — grid. Nesting flex to fake a 2D grid is a smell.
flex: 1(basis 0) vsflex: auto(basis auto) is a real decision: equal columns vs content-weighted columns. Picking the wrong one causes "why is this column wider?" confusion.gapover margins.gapexpresses spacing intent, avoids the first/last-child margin dance, and doesn't leak to the container edges.- Don't over-nest. Deeply nested flex containers get hard to reason about; flatten with grid or
display: contentswhere it helps.
💣 Gotchas interviewers probe
min-width: autooverflow. The question. Flex items won't shrink below their content's min size;min-width: 0(row) /min-height: 0(column) releases the floor. Explaining why — the auto min-size rule — is the senior signal.flex-basisbeatswidth. When both are set,flex-basiswins on the main axis.basis: 0vsautochanges distribution entirely.flex-shrinkis weighted by basis, not just the ratio: a larger item gives up proportionally more space. Not a plain 1:1.align-itemsvsalign-content.align-itemsaligns items on the cross axis;align-contentdistributes wrapped lines and only does anything when there are multiple lines (flex-wrap: wrap).margin: autoabsorbs free space on any side — the cleanest push-apart and even for centering (including vertical, which margin auto can't do in normal flow).- Percentage
flex-basisneeds a definite container size on the main axis, or it falls back to content.
🎯 Say this in the interview
"Flexbox is one-dimensional: items lay out along a main axis and the algorithm distributes leftover space. Each item starts at its
flex-basis, thenflex-growhands out extra space andflex-shrinkclaws it back when there isn't enough. The distinction I always make isflex: 1, which is1 1 0— basis zero, so items split space equally regardless of content — versusflex: auto, which is basisauto, so items keep their content size and only share the extra. The gotcha I'd lead with is overflow: a flex item's defaultmin-widthisauto, which resolves to its min-content size — the longest word or an image's intrinsic width — so it refuses to shrink below that and blows out the container. The fix ismin-width: 0on the item, ormin-height: 0in a column. That one rule explains ninety percent of 'why is my flex layout overflowing' bugs. For spacing I usegap, andmargin: autofor push-apart since it absorbs free space on whichever side you put it."
🔗 Go deeper
- CSS-Tricks — A Complete Guide to Flexbox — the canonical property-by-property reference.
- MDN — Basic concepts of flexbox — axes, basis, and the sizing algorithm.
- MDN — Controlling ratios of flex items — grow/shrink/basis and the min-size floor.