Flexbox
One-dimensional layout with Tailwind — direction, alignment, wrapping, grow and shrink — and the handful of patterns that cover most real interfaces.
Flexbox lays out children along a single axis and distributes the free space between them. It is the right tool for toolbars, navigation, button groups, form rows and card internals.
Overview#
<div class="mx-auto flex max-w-2xl items-center justify-between gap-4 rounded-xl border border-gray-200 bg-white px-6 py-4">
<span class="font-semibold text-gray-900">Acme Inc.</span>
<nav class="flex items-center gap-6 text-sm text-gray-600">
<a href="#" class="hover:text-gray-900">Product</a>
<a href="#" class="hover:text-gray-900">Pricing</a>
<a href="#" class="hover:text-gray-900">Docs</a>
</nav>
<button class="rounded-md bg-gray-900 px-3 py-1.5 text-sm font-medium text-white hover:bg-gray-700">Sign in</button>
</div>That is flex items-center justify-between gap-4 — four classes for a complete header.
The two axes#
Everything in Flexbox depends on which direction is "main".
| Direction | Main axis | Cross axis | Controlled by |
|---|---|---|---|
flex-row (default) | Horizontal | Vertical | justify-* / items-* |
flex-col | Vertical | Horizontal | justify-* / items-* |
justify-*distributes along the main axis.items-*aligns along the cross axis.
Container utilities#
Direction#
| Utility | CSS |
|---|---|
flex-row | flex-direction: row |
flex-row-reverse | row-reverse |
flex-col | column |
flex-col-reverse | column-reverse |
Justify — main axis#
| Utility | Result |
|---|---|
justify-start | Packed at the start |
justify-center | Packed in the middle |
justify-end | Packed at the end |
justify-between | First and last at the edges, equal gaps between |
justify-around | Equal space around each item |
justify-evenly | Equal space between and at the edges |
justify-center-safe | Like center, but falls back to start when overflowing v4.1 |
<div class="space-y-2 p-4 text-xs">
<div class="flex justify-start gap-1 rounded bg-gray-100 p-2"><span class="rounded bg-indigo-500 px-3 py-1 text-white">1</span><span class="rounded bg-indigo-500 px-3 py-1 text-white">2</span><span class="rounded bg-indigo-500 px-3 py-1 text-white">3</span></div>
<div class="flex justify-center gap-1 rounded bg-gray-100 p-2"><span class="rounded bg-indigo-500 px-3 py-1 text-white">1</span><span class="rounded bg-indigo-500 px-3 py-1 text-white">2</span><span class="rounded bg-indigo-500 px-3 py-1 text-white">3</span></div>
<div class="flex justify-between rounded bg-gray-100 p-2"><span class="rounded bg-indigo-500 px-3 py-1 text-white">1</span><span class="rounded bg-indigo-500 px-3 py-1 text-white">2</span><span class="rounded bg-indigo-500 px-3 py-1 text-white">3</span></div>
<div class="flex justify-evenly rounded bg-gray-100 p-2"><span class="rounded bg-indigo-500 px-3 py-1 text-white">1</span><span class="rounded bg-indigo-500 px-3 py-1 text-white">2</span><span class="rounded bg-indigo-500 px-3 py-1 text-white">3</span></div>
</div>Items — cross axis#
| Utility | Result |
|---|---|
items-start | Aligned to the cross-axis start |
items-center | Centred |
items-end | Aligned to the end |
items-baseline | Text baselines line up |
items-baseline-last | Aligned on the last baseline v4.1 |
items-stretch | Default — fill the cross axis |
items-center-safe | Centre, but do not push content out of view v4.1 |
items-baseline is worth knowing: it aligns text of different sizes on the line they sit on, rather than by box.
<div class="flex items-baseline gap-2 p-4">
<span class="text-3xl font-bold text-gray-900">$29</span>
<span class="text-sm text-gray-500">per month</span>
</div>Wrapping#
| Utility | CSS |
|---|---|
flex-wrap | Items wrap onto new lines |
flex-nowrap | Default — items shrink instead of wrapping |
flex-wrap-reverse | Wrap upwards |
content-* | Aligns the lines when wrapped (content-start, content-between, …) |
Gap#
gap-4, gap-x-4, gap-y-2 set spacing between items.
Item utilities#
| Utility | CSS | Meaning |
|---|---|---|
grow | flex-grow: 1 | Absorb free space |
grow-0 | flex-grow: 0 | Do not grow (default) |
shrink | flex-shrink: 1 | May shrink (default) |
shrink-0 | flex-shrink: 0 | Never shrink |
flex-1 | flex: 1 1 0% | Equal share, ignoring content width |
flex-auto | flex: 1 1 auto | Grow and shrink, starting from content width |
flex-initial | flex: 0 1 auto | Shrink only |
flex-none | flex: none | Fixed size |
basis-* | flex-basis | Starting size along the main axis |
order-* | order | Visual reordering |
self-* | align-self | Override items-* for one item |
flex-1 vs flex-auto#
<div class="space-y-3 p-4 text-xs">
<div>
<p class="mb-1 font-mono text-gray-500">flex-1 — equal widths regardless of content</p>
<div class="flex gap-2">
<div class="flex-1 rounded bg-indigo-500 p-2 text-white">Short</div>
<div class="flex-1 rounded bg-indigo-500 p-2 text-white">Much, much longer content here</div>
</div>
</div>
<div>
<p class="mb-1 font-mono text-gray-500">flex-auto — sized by content, then shares the rest</p>
<div class="flex gap-2">
<div class="flex-auto rounded bg-emerald-600 p-2 text-white">Short</div>
<div class="flex-auto rounded bg-emerald-600 p-2 text-white">Much, much longer content here</div>
</div>
</div>
</div>Use flex-1 for equal columns; flex-auto when content should influence the split.
Common patterns#
Media object#
<div class="mx-auto flex max-w-md items-start gap-4 rounded-xl border border-gray-200 p-4">
<div class="size-12 shrink-0 rounded-full bg-gradient-to-br from-indigo-400 to-purple-500"></div>
<div class="min-w-0">
<p class="font-medium text-gray-900">Casey Rivera</p>
<p class="truncate text-sm text-gray-500">Commented on your pull request about the new layout engine</p>
</div>
</div>Two critical classes here:
shrink-0on the avatar so it never squashes.min-w-0on the text sotruncatecan work.
Push one item to the end#
<div class="flex items-center gap-4">
<span>Logo</span>
<nav class="flex gap-4">…</nav>
<button class="ml-auto">Sign in</button>
</div>ml-auto absorbs all free space to the left of the button — more flexible than justify-between when there are three or more groups.
Sticky footer#
<body class="flex min-h-screen flex-col">
<header>…</header>
<main class="flex-1">…</main>
<footer>…</footer>
</body>flex-1 on <main> pushes the footer to the bottom on short pages.
Responsive stack#
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">…</div>Equal-height cards in a row#
<div class="flex gap-4">
<article class="flex flex-1 flex-col rounded-xl border p-4">
<h3 class="font-semibold">Title</h3>
<p class="text-sm text-gray-600">Varying amounts of text.</p>
<button class="mt-auto pt-4 text-sm text-indigo-600">Read more</button>
</article>
…
</div>items-stretch (the default) makes cards equal height; mt-auto pins each footer to the bottom.
Common mistakes#
justify-centerfor vertical centring in a row. Useitems-center.- Missing
min-w-0when truncating. The number one reasontruncate"doesn't work". - Missing
shrink-0on icons and avatars. They get squashed when siblings are long. - Using
space-x-*wheregapfits.gapis simpler and behaves correctly with wrapping. flex-wrapwithoutgap. Wrapped rows will collide.- Reordering with
order-*and forgetting keyboard users. Visual order changes; tab order does not. Only reorder when they still agree.