ESC

Type to search the knowledge base.

Flex Grow Shrink Basis

How flex items resolve size — flex-basis first, then grow into free space and shrink on deficit, plus min-width:auto overflow fixes.

intermediate3 min read
  • css
  • flexbox
  • flex-grow

Flex sizing is a three-step story: flex-basis (starting main size), flex-grow (share of leftover free space), flex-shrink (share of overflow deficit). The shorthand flex sets all three; misremembering the defaults is why “flex: 1 vs flex: auto” shows up in interviews.

Docs: MDN flex, flex-grow, flex-basis.

The algorithm (simplified)

  1. Resolve each item’s base size from flex-basis (and width/height rules when basis is auto).
  2. If free space remains on the main axis, distribute it proportional to flex-grow.
  3. If items overflow, reduce sizes proportional to flex-shrink × base size (roughly).
  4. Clamp by min-width / max-width (and the automatic minimum size).
.item {
  flex: 1 1 0%; /* grow, shrink, basis */
}

Common shorthands

Shorthand Expand Typical use
flex: 0 1 auto default Size to content, can shrink
flex: none 0 0 auto Rigid content size
flex: auto 1 1 auto Grow/shrink from content size
flex: 1 1 1 0% Equal flexible columns from zero basis
flex: 2 2 1 0% Double share of free space vs flex: 1 peers
.layout {
  display: flex;
  gap: 1rem;
}

.sidebar {
  flex: 0 0 16rem; /* fixed rail */
}

.main {
  flex: 1 1 auto;
  min-width: 0; /* allow shrink below content min */
}

flex-basis details

.a { flex-basis: 200px; }
.b { flex-basis: 30%; }   /* % of flex container inner main size */
.c { flex-basis: auto; }  /* look at width/height / content */
.d { flex-basis: content; } /* size based on content (support varies historically) */

flex: 1 using 0% basis means equal distribution ignores content width differences when growing — usually what you want for equal columns. flex: auto starts from content, so a wide image item stays wider before free space is shared.

Grow ratios

.col-1 { flex-grow: 1; }
.col-2 { flex-grow: 2; } /* gets twice the *extra* space, not twice total width */

Grow only distributes remaining free space after bases are placed.

Shrink and the min-size footgun

By default min-width: auto (in a row flex) prevents items from shrinking smaller than their content’s minimum. Long strings and wide tables blow the layout.

.main {
  flex: 1;
  min-width: 0;
  overflow: auto;
}

/* column flex: */
.scroll-pane {
  flex: 1;
  min-height: 0;
  overflow: auto;
}

flex-shrink: 0 on an icon keeps it from being crushed:

.icon {
  flex: 0 0 auto;
}

Worked equal columns

<div class="stats">
  <div class="stat">12</div>
  <div class="stat">348</div>
  <div class="stat">5</div>
</div>
.stats {
  display: flex;
  gap: 0.75rem;
}

.stat {
  flex: 1 1 0;
  min-width: 0;
  padding: 1rem;
  text-align: center;
}

Interview out-loud

“flex-basis is the starting main size, flex-grow shares free space, flex-shrink shares deficit. flex: 1 is 1 1 0% for equal flexible tracks; flex: auto is 1 1 auto from content size. The default min-size can block shrinking — set min-width: 0 (or min-height: 0 in a column) on scrollable flex children.”

Footguns

  1. Using % basis without a definite container size.
  2. Forgetting gap is outside flex base calculations in ways that surprise (still budget for gap).
  3. Nested flex without min-size zero → can’t scroll.
  4. Animating flex-grow for performance-sensitive UI.
  5. Mixing width and flex-basis without knowing which wins in context.

Further reading

Related guides