Flexbox in Depth
Prerequisites: Specificity in depth
flex-grow, flex-shrink, flex-basis
Each flex item has three sizing properties, usually set together with
the flex shorthand:
flex-basis— the starting size before free space is shared (auto= usewidthor the content size).flex-grow— how much of the leftover space the item takes, relative to the others.flex-shrink— how much it gives up when there isn't enough space.
| Shorthand | Means | Use for |
|---|---|---|
flex: initial |
0 1 auto |
The default: don't grow, may shrink |
flex: 1 |
1 1 0% |
Share space equally, ignoring content size |
flex: auto |
1 1 auto |
Grow, but start from the content size |
flex: none |
0 0 auto |
Rigid: never grow or shrink |
<style>
.row { display: flex; width: 600px; }
.row > div { flex-basis: 100px; }
.g1 { flex-grow: 1; }
.g2 { flex-grow: 2; }
.equal { display: flex; width: 600px; }
.equal > div { flex: 1; }
</style>
<div class="row"><div class="g0">A</div><div class="g1">B</div><div class="g2">C</div></div>
<div class="equal"><div>short</div><div>a much longer piece of content</div><div>x</div></div>
<script>
const widths = sel => [...document.querySelectorAll(sel)].map(el => el.getBoundingClientRect().width);
console.log("grow 0/1/2:", widths(".row > div").join(", "));
console.log("flex: 1 :", widths(".equal > div").join(", "));
</script>
grow 0/1/2: 100, 200, 300
flex: 1 : 200, 200, 200
- First row: three 100px bases leave 300px free. It's split 0 : 1 : 2, so B gets +100 and C +200.
- Second row:
flex: 1sets the basis to 0, so all 600px are shared equally, whatever the content length.
The min-width: auto trap
Flex items won't shrink below their minimum content size by default
(min-width: auto). A long URL or a pre block can therefore push a
flex layout wider than the screen. The fix:
.main-column {
flex: 1;
min-width: 0;
}
Alignment details
.toolbar { display: flex; align-items: center; }
.toolbar .title { align-self: flex-start; }
.toolbar .spacer { flex: 1; }
.gallery { display: flex; flex-wrap: wrap; align-content: flex-start; }
.cards { display: flex; align-items: stretch; }
align-selfoverridesalign-itemsfor one item.align-contentdistributes lines when items wrap.stretch(the default) makes items in a row equal height — why flex "equal-height columns" just work.orderchanges visual order — but not the tab or reading order. Use it sparingly, for accessibility.
Flexbox or Grid?
- Flexbox: one dimension. Content decides the sizes; items flow and wrap. Toolbars, nav bars, tags, a row of buttons.
- Grid: two dimensions. The layout decides the sizes; items line up in rows and columns. Page layouts, card grids, forms.
Practice
A media object: an image of fixed width 96px on the left and text that fills the rest, with the image not shrinking and the text allowed to shrink below its content width.
Show solution
.media {
display: flex;
gap: 1rem;
align-items: flex-start;
}
.media img {
flex: none;
width: 96px;
}
.media .body {
flex: 1;
min-width: 0;
}