Skip to content
AgileLogics
7 min read

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 = use width or 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: 1 sets 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-self overrides align-items for one item.
  • align-content distributes lines when items wrap.
  • stretch (the default) makes items in a row equal height — why flex "equal-height columns" just work.
  • order changes 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;
}