AniUI Academy

Flexbox in Practice

Real flexbox patterns — a navbar with space-between, equal-height cards via stretch, centering with justify-content/align-items, gap instead of margin hacks, order, and align-self.

9 min read

The previous lesson covered flexbox's individual properties in isolation. Real layouts combine a handful of them to solve specific, recurring problems. Every pattern below is one you'll rebuild constantly — worth recognizing on sight rather than reasoning out from scratch each time.

.navbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
<nav class="navbar">
  <div class="logo">AniUI</div>
  <div class="links">
    <a href="#">Home</a>
    <a href="#">Courses</a>
    <a href="#">About</a>
  </div>
</nav>

Two direct children — the logo and the links wrapper — get pushed to opposite ends of the row by space-between, with align-items: center keeping both vertically centered regardless of whether the logo or the links happen to be taller.

Equal-height cards, for free

.card-row {
  display: flex;
  gap: 1.5rem;
}
.card {
  flex: 1;
  padding: 1.5rem;
}

Give a row of cards no explicit height at all, and they still end up the exact same height as each other — whichever one has the most content. That's the default align-items: stretch from the previous lesson doing the work: every flex item stretches to match the tallest one on the cross axis, with zero extra code. This is one of flexbox's most-used behaviours precisely because it requires nothing extra to trigger — it's just what happens unless you override it.

Perfectly centering content, both axes

.centered {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 300px;
}

This is the classic answer to "how do I center a div" — a question with a reputation for having a surprisingly annoying answer in old CSS. With flexbox it's three lines: justify-content: center centers along the main axis, align-items: center centers along the cross axis, and together they center a single child both horizontally and vertically inside its container, regardless of the child's own size.

gap: spacing without margin hacks

Before gap existed on flex containers, spacing a row of items required margin on each item — and margin on every item includes one after the last item too, creating an unwanted extra gap at the row's edge that then needed a :last-child override to remove.

/* the old way */
.item { margin-right: 1rem; }
.item:last-child { margin-right: 0; }
 
/* the gap way */
.container { display: flex; gap: 1rem; }

gap only ever inserts space between items — never before the first or after the last — so there's no edge case to special-case away. It's the preferred way to space out flex items today, and it works for both flex-direction: row and column.

order: reordering visually without touching the HTML

.item-a { order: 2; }
.item-b { order: 1; }

By default every flex item has order: 0, and items with equal order values keep their source order relative to each other. Give an item a different order value and it visually moves to sit among items with that value, without changing a single line of HTML.

This is useful for things like moving a "featured" card to the front on larger screens while keeping the HTML in a sensible, logical reading order. It's worth using sparingly, though — order only changes visual order; the underlying HTML source order (and generally the order a screen reader announces content in, and the order keyboard Tab navigation follows) stays based on the document, not on order. A large mismatch between visual order and source order can genuinely confuse someone navigating by keyboard or screen reader, even though it looks fine visually.

align-self: overriding one item's cross-axis alignment

.container {
  display: flex;
  align-items: center; /* every item centered on the cross axis, by default */
}
.item-special {
  align-self: flex-end; /* except this one, pinned to the cross-axis end */
}

align-items on the container sets the default for every item. align-self, set on one specific item, overrides that default just for that item — useful for something like a "new" badge that should sit at the bottom of an otherwise vertically-centered row of icons.

Try it yourself

A navbar with space-between, a row of cards proving equal-height stretch, a perfectly centered box, and one card using both order (moved visually first) and align-self (pinned to the bottom of its row) — all in one page.

Try it yourself
Loading playground...

What to remember

  • A navbar with a logo and nav links uses justify-content: space-between to push them to opposite ends.
  • Equal-height cards come from the default align-items: stretch — no extra code required.
  • justify-content: center; align-items: center; on the container is the standard way to center a single child on both axes.
  • gap spaces items out without the last-item margin hack that manual margins require.
  • order reorders items visually only — source order, and typically screen-reader and keyboard order, stay unchanged.
  • align-self on an individual item overrides the container's align-items for that one item only.

Check yourself

4 questions · pass 3/4 to unlock CSS Grid Fundamentals

up to 50
  1. 1.What is the classic flexbox answer to 'how do I center a div, both horizontally and vertically'?

  2. 2.Why is gap preferred over adding margin to flex items for spacing?

  3. 3.What does align-self do differently from align-items?

  4. 4.Does the order property change the actual order of elements in the HTML source?

4 left to answer