Articles

CSS Flexbox: flex-grow, flex-shrink, flex-basis Explained

How flex-grow, flex-shrink, and flex-basis actually distribute space in a flex container, with the flex shorthand values worth memorizing.

Takina Takina · · 4 min read
Close-up of CSS code on a screen

flex-grow, flex-shrink, and flex-basis are the three properties that control how a flex item’s size is calculated inside a flex container — together they decide how leftover space gets handed out and how items give space back when the container is too small. They’re almost always set through the flex shorthand rather than individually, but understanding what each one does on its own makes the shorthand’s values obvious instead of arbitrary.

Container vs items

Flexbox splits responsibilities cleanly: properties on the container (display: flex, flex-direction, justify-content, align-items) control the layout as a whole, while flex-grow, flex-shrink, and flex-basis are set on the children and control how each one individually competes for space along the main axis. See flexbox vs grid for when one-dimensional flex layout is the right tool versus two-dimensional grid.

flex-basis: the starting size

flex-basis sets an item’s initial size along the main axis before any growing or shrinking happens. It behaves like width (in a row-direction container) but takes priority over it when both are set. It accepts any length (200px, 20%) or the keyword auto, which falls back to the item’s own width/height or its content size.

.item {
  flex-basis: 240px;
}

Think of flex-basis as “the size the browser starts from” — flex-grow and flex-shrink then adjust from that starting point based on how much space is available.

flex-grow: distributing extra space

flex-grow is a unitless number that determines how much of the leftover space (container size minus the sum of all items’ basis sizes) an item absorbs, relative to the other items’ flex-grow values. It defaults to 0, meaning items don’t grow at all by default.

If three items all have flex-grow: 1, leftover space is split evenly three ways. If one item has flex-grow: 2 and the others have flex-grow: 1, that item gets twice as much of the leftover space as each of the others — not twice the total width, just twice the extra portion.

.sidebar { flex-grow: 0; }  /* stays at its basis size */
.main    { flex-grow: 1; }  /* absorbs all remaining space */

flex-shrink: giving up space

flex-shrink is the mirror image: when the container is too small to fit every item at its basis size, flex-shrink determines how much each item gives up, proportional to its value and its own basis size. It defaults to 1, so items shrink by default — a common surprise for developers who expect flex-basis or width to be a hard floor. Setting flex-shrink: 0 pins an item to its basis size no matter how cramped the container gets, which is the usual fix for icons or badges that shouldn’t compress.

The flex shorthand

Writing all three properties out is verbose, so flex combines them: flex: <grow> <shrink> <basis>. A handful of shorthand values cover almost every real layout:

ShorthandExpands toMeaning
flex: initial0 1 autoDefault. Sized by content/width; can shrink, won’t grow.
flex: auto1 1 autoSized by content/width; can grow and shrink.
flex: none0 0 autoFixed at content/width size; can’t grow or shrink.
flex: 11 1 0%Ignores content size; splits space evenly with siblings on flex: 1.
flex: 0 0 200px—Fixed 200px, immune to growing or shrinking.

flex: 1 is the one worth memorizing separately from the others: setting flex-basis to 0% means the item’s content size is ignored entirely as a starting point, so several flex: 1 siblings end up genuinely equal-width regardless of how much text or content each one holds. flex: auto looks similar but starts from content size, so items with more content stay slightly larger even after growing.

Common patterns

  • Sidebar + main content. .sidebar { flex: 0 0 240px; } and .main { flex: 1; } gives a fixed sidebar and a main area that fills the rest, without a single media query.
  • Equal-width columns. Give every child flex: 1 and the container display: flex; use the gap property instead of margins to space them.
  • Preventing squish. Add flex-shrink: 0 to fixed-size elements like avatars or icon buttons sitting next to flexible text, so they don’t get compressed when space runs short.
  • Wrapping. flex-wrap: wrap on the container turns overflowing items into new rows; combine with flex-basis (e.g. flex-basis: 30%) to control roughly how many items fit per row before it wraps.

Flexbox vs grid

Flexbox is one-dimensional — it excels at distributing items along a single row or column, which is exactly what flex-grow/flex-shrink/flex-basis are built for. When you need alignment across both rows and columns simultaneously — a card grid where items line up in a strict matrix — CSS Grid is usually the better model, and its own space-distribution keywords like minmax() and repeat() solve a similar problem in two dimensions. Container queries can complement either layout method when an item’s own size, not just the viewport’s, should drive its styling — see CSS container queries.

The takeaway

flex-basis sets an item’s starting size, flex-grow distributes leftover space, and flex-shrink takes space back when the container is too small — each defaults to a value (auto, 0, 1 respectively) that trips people up until you know it. In practice, reach for the flex shorthand: flex: 1 for items that should split space evenly regardless of content, flex: auto when content size should still matter, flex: none for items that must never resize, and an explicit flex: 0 0 <size> for anything pinned to a fixed width.

Takina Takina · · 4 min read

Container Query Units: cqw, cqh, and cqi Explained

Container query units like cqw and cqi size elements relative to their containing element, not the viewport — here's how and when to use them.

#CSS #Web Development #Frontend