AniUI Academy

Flexbox Fundamentals

display flex and the main axis — flex-direction, justify-content, align-items, flex-wrap, and the flex-grow/shrink/basis shorthand that makes items share space.

9 min read

Everything you've laid out so far has relied on normal document flow — block elements stacking vertically, inline elements flowing like text. Flexbox is the first real layout system in this course: set display: flex on a container, and every one of its direct children becomes a flex item that the container can align, space out, and resize along a single axis.

Turning on flex

.container {
  display: flex;
}

That one line changes how every direct child of .container behaves. They stop stacking as blocks and instead line up along the main axis — by default, a horizontal row, left to right.

<div class="container">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
</div>

Nothing here has been told to be "flex items" explicitly — becoming a flex item is just what happens to any direct child of an element with display: flex. Grandchildren aren't affected; only direct children are.

flex-direction: which axis is the main one

.container {
  display: flex;
  flex-direction: row; /* default */
}
  • row (default) — main axis is horizontal, items flow left to right.
  • row-reverse — main axis is horizontal, items flow right to left.
  • column — main axis is vertical, items flow top to bottom.
  • column-reverse — main axis is vertical, items flow bottom to top.

This choice is what defines which axis is "main" and which is "cross" for every other flex property below. With row, main is horizontal and cross is vertical. With column, that flips: main is vertical, cross is horizontal. Every alignment property you're about to see keeps meaning the same thing — "main axis" or "cross axis" — but which physical direction that refers to depends entirely on flex-direction.

justify-content: aligning along the main axis

.container {
  display: flex;
  justify-content: center;
}
  • flex-start (default) — items packed at the start of the main axis.
  • center — items packed together in the middle.
  • space-between — first item flush to the start, last item flush to the end, remaining space distributed evenly between items.
  • space-around — equal space around every item, including half-spaces at the two outer edges.

This is the property you reach for constantly for things like a navbar with items spread across the full width (space-between) or a button group centered in its container (center).

align-items: aligning along the cross axis

.container {
  display: flex;
  align-items: center;
}
  • stretch (default) — items stretch to fill the container's cross-axis size, unless they have their own explicit size set.
  • center — items centered on the cross axis.
  • flex-start — items aligned to the cross-axis start.
  • flex-end — items aligned to the cross-axis end.

stretch being the default is worth internalizing, because it explains a lot of flexbox behaviour that looks like magic the first time you see it: a row of boxes with no height set on any of them will naturally all become the same height — the height of the tallest one — because every item stretches to fill the row's cross-axis size unless you tell it not to.

flex-wrap: what happens when items don't fit

.container {
  display: flex;
  flex-wrap: nowrap; /* default */
}

By default (nowrap), flex items are forced onto a single line — if they don't all fit, they shrink (if allowed) or overflow the container. Setting flex-wrap: wrap lets items that don't fit flow onto additional lines instead, much like words wrapping in a paragraph.

.container {
  display: flex;
  flex-wrap: wrap;
}

This is essential for anything like a tag list or a card grid built with flexbox, where the number of items isn't fixed and the container might not be wide enough for all of them on one line.

flex-grow, flex-shrink, flex-basis, and the flex shorthand

Each flex item can individually control how it grows, shrinks, and what its starting size is, before the container's justify-content/align-items even come into play:

  • flex-basis — the item's starting main-axis size, before growing or shrinking is applied. Can be a length (200px) or auto (use the item's own width/height or content size).
  • flex-grow — how much of the container's leftover space this item should claim, relative to its siblings. 0 (default) means don't grow at all.
  • flex-shrink — how much this item should shrink if the container is too small to fit everyone at their basis size. 1 (default) means shrink proportionally along with everyone else.

These three are almost always written together as the flex shorthand:

.item {
  flex: 1;
  /* shorthand for: flex-grow: 1; flex-shrink: 1; flex-basis: 0%; */
}

flex: 1 on every child of a container is the single most common flexbox pattern there is: every item starts from a zero basis and grows to fill the container, so they end up sharing all available space equally. Give one item flex: 2 among siblings with flex: 1, and it claims twice as much of the leftover space as each of them.

.sidebar { flex: 0 0 250px; }  /* fixed 250px, never grows, never shrinks */
.main    { flex: 1; }           /* takes up everything else */

This pairing — one fixed-width item plus one flex: 1 item — is exactly how a sidebar-plus-content layout is built with flexbox, without a single width percentage anywhere.

Try it yourself

A row of three flex items demonstrates justify-content: space-between, the default align-items: stretch making every box the same height despite different content, and one item using flex: 2 to claim double the space of its flex: 1 siblings.

Try it yourself
Loading playground...

What to remember

  • display: flex turns direct children into flex items arranged along a main axis.
  • flex-direction decides which axis is main (row/row-reverse horizontal, column/column-reverse vertical) — every other property below follows from that.
  • justify-content aligns along the main axis; align-items aligns along the cross axis, defaulting to stretch.
  • flex-wrap: nowrap (default) forces one line; wrap lets items flow onto new lines.
  • flex-grow/flex-shrink/flex-basis, usually written as the flex shorthand, control how items grow and shrink — flex: 1 on every child is the standard "share remaining space equally" pattern.

Check yourself

4 questions · pass 3/4 to unlock Flexbox in Practice

up to 50
  1. 1.With flex-direction: row (the default), which axis does justify-content control?

  2. 2.What does align-items: stretch, the default, do to flex items with no explicit height?

  3. 3.What does flex: 1 on every child of a flex container do?

  4. 4.By default, does display: flex wrap items onto a new line when they don't fit?

4 left to answer