Flexbox in one sentence
Add flex to a parent and its children stop stacking and start sitting in a row, and you get two superpowers: control over spacing along the row (justify-) and alignment across it (items-).
90% of everyday layout — navbars, toolbars, list rows, button groups, centering — is flexbox. Learn these utilities cold.
The core utilities
| Utility | CSS | Controls |
|---|---|---|
flex | display: flex | turns on flexbox (row by default) |
flex-col | flex-direction: column | stack children vertically |
justify-start/center/end | justify-content | position along the main axis |
justify-between | space pushed between items | navbars: logo left, menu right |
justify-around / justify-evenly | distributed spacing | equal gaps around items |
items-start/center/end | align-items | alignment on the cross axis |
items-baseline | align text baselines | price + "/month" pairs |
gap-4 | gap: 1rem | space between children (both axes) |
flex-wrap | flex-wrap: wrap | allow items to wrap to next line |
The most important class combo in Tailwind: flex items-center justify-between. Say it like a mantra. It builds navbars, card headers, list rows, footers — anything with "stuff on the left, stuff on the right, all vertically centered".
Perfect centering (finally easy)
Centering a child both ways used to be a running joke in CSS. Now:
<div class="flex items-center justify-center min-h-screen">
<div>I am perfectly centered</div>
</div>
justify-center centers horizontally (main axis), items-center centers vertically (cross axis). Note: in flex-col, the axes swap — justify- becomes vertical and items- horizontal. If alignment ever "does the wrong thing", check the direction first.
How children grow and shrink
| Utility | Meaning |
|---|---|
flex-1 | grow to fill all leftover space (equal share) |
flex-none | never grow, never shrink — stay natural size |
grow | allow growing only |
shrink-0 | never shrink (critical for avatars & icons!) |
basis-1/3 | starting size before grow/shrink |
The classic media object — avatar left, text right, text takes the rest:
<div class="flex items-center gap-4">
<img class="size-12 rounded-full shrink-0" src="avatar.jpg" alt="">
<div class="flex-1 min-w-0">
<p class="font-semibold text-slate-900">Priya Sharma</p>
<p class="text-sm text-slate-500 truncate">Completed the Flexbox lesson and started…</p>
</div>
<span class="text-xs text-slate-400 shrink-0">2m ago</span>
</div>
Two subtle pro details in there:
shrink-0on the avatar — without it, long text squishes the image into an oval.min-w-0on the text block — flex children refuse to shrink below their content's width by default, which breakstruncate.min-w-0fixes the single most confusing flexbox bug you will ever meet.
gap vs space-x
Both create spacing between children. gap-4 is the flexbox-native way and handles wrapping correctly (space-x puts margin on wrapped lines' first items where you don't want it). Rule: inside flex or grid, always prefer gap-*.
Pattern 1 — the navbar
<nav class="flex items-center justify-between px-6 py-4 bg-white shadow-sm">
<span class="font-extrabold text-slate-900">Brand</span>
<div class="flex items-center gap-6 text-sm text-slate-600">
<a href="#" class="hover:text-teal-600">Courses</a>
<a href="#" class="hover:text-teal-600">Pricing</a>
<a href="#" class="bg-teal-600 text-white px-4 py-2 rounded-lg hover:bg-teal-500">Sign up</a>
</div>
</nav>
One outer justify-between splits brand from menu; one inner flex gap-6 spaces the links. Nested flex containers — outer for macro layout, inner for micro — is how every real interface is built.
Pattern 2 — sticky footer
Page shorter than the screen, but the footer must sit at the bottom:
<body class="flex flex-col min-h-screen">
<nav>…</nav>
<main class="flex-1">…</main> <!-- flex-1 absorbs the leftover height -->
<footer>…</footer>
</body>
Pattern 3 — equal-height cards
Cards in a flex row are equal height automatically (items-stretch is the default). To pin the button of each card to its bottom regardless of text length: make each card flex flex-col and give the description flex-1, which pushes the button down.
Utilities for individual children
self-end,self-center— override the parent'sitems-*for one childorder-first,order-last— reorder visually without moving the HTMLml-auto— the flexbox "push everything after me to the right" trick (e.g. one button pushed to the row's end)
Common beginner mistakes
- Forgetting the axes swap in
flex-col— vertical centering suddenly needsjustify-center, notitems-center. - Squished avatars — add
shrink-0to any fixed-size child sitting next to long text. truncatenot truncating — the flex child needsmin-w-0.- Margins for spacing between flex children — use
gap-*; margins fight with wrapping andjustify-between.
Practice task
In the editor: (1) make the chat rows reverse for the second message (sender on the right) using flex-row-reverse, (2) pin the "Send" button to the right edge of the composer with ml-auto instead of justify-between, (3) add a third chat row and watch the equal spacing come from space-y-4, not margins.