06 · Layout & Flexbox Utilities¶
Tailwind's layout utilities are thin wrappers over CSS layout properties, so the real skill is knowing Flexbox and Grid; the class names come quickly after that. This lesson maps Flexbox to its utilities, measures the handful whose behaviour surprises people, and covers display, positioning and z-index. (For the underlying algorithm, see Flexbox Fundamentals and Flexbox in Depth in the HTML & CSS course.)
Display¶
block, inline-block, inline, flex, inline-flex, grid, inline-grid,
contents, flow-root, table, hidden (display: none). sr-only hides something
visually but keeps it for screen readers (Level 3 · 04).
Flex containers¶
| Utility | CSS |
|---|---|
flex |
display: flex |
flex-row / flex-col / flex-row-reverse |
flex-direction |
flex-wrap / flex-nowrap |
flex-wrap |
justify-start center end between around evenly |
justify-content |
items-start center end baseline stretch |
align-items |
content-* |
align-content (multi-line) |
gap-4, gap-x-6, gap-y-2 |
gap |
<header class="flex flex-wrap items-center gap-x-6 gap-y-2 p-4">
<a class="font-bold" href="/">Weeknight Kitchen</a>
<nav class="ms-auto" aria-label="Main">
<ul class="flex gap-4">
<li><a href="/recipes">Recipes</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
ms-auto (margin-inline-start: auto) pushes the nav to the end — an auto margin
absorbs free space before justify-content does.
Flex items¶
| Utility | CSS | Use |
|---|---|---|
flex-1 |
flex: 1 (= 1 1 0%) |
Equal-width columns, ignoring content |
flex-auto |
flex: auto (= 1 1 auto) |
Start at content size, share leftover |
flex-initial |
flex: 0 1 auto |
The CSS default |
flex-none |
flex: none |
Rigid: never grow or shrink |
grow, grow-0 |
flex-grow |
|
shrink, shrink-0 |
flex-shrink |
shrink-0 on icons and avatars |
basis-64, basis-1/3 |
flex-basis |
|
order-first, order-last, order-2 |
order |
Visual only — see below |
self-start, self-center… |
align-self |
flex-1 vs flex-auto, measured¶
Three items with different amounts of text in a 600px row:
flex-1 sets the basis to 0, so all the space is shared equally regardless of content.
flex-auto starts from each item's content width and only shares the leftover, so the
longer item stays wider. Choose deliberately — most "why are my columns unequal?" questions
are a flex-auto that should have been flex-1, or the reverse.
The truncate trap, measured¶
A notification row: a 24px icon, then a title that should truncate. Three versions in a 300px flex row, measuring the text box:
<!-- A: truncate on the flex item itself -->
<div class="flex w-[300px] items-center gap-2">
<span class="size-6 shrink-0"></span>
<p class="truncate">A very long notification title that should be truncated nicely</p>
</div>
<!-- B: truncate inside a wrapper div -->
<div class="flex …"><span …></span><div><p class="truncate">…</p></div></div>
<!-- C: same, with min-w-0 on the wrapper -->
<div class="flex …"><span …></span><div class="min-w-0"><p class="truncate">…</p></div></div>
A: text width 268, row scrollWidth 300 (truncated correctly)
B: text width 427, row scrollWidth 459 (overflowed the row)
C: text width 268, row scrollWidth 300 (truncated correctly)
In A, truncate sets overflow: hidden on the flex item itself, which also removes its
automatic minimum size. In B, the wrapper div is the flex item, and flex items default
to min-width: auto — "never narrower than my content" — so it grew to the full text
width and overflowed. min-w-0 on the flex item (C) is the fix. The same applies to
code blocks, long URLs and tables inside flex children.
Visual order and accessibility¶
order-*, flex-row-reverse and flex-col-reverse change what you see but not the DOM
order — which is the keyboard and screen-reader order. Use them only when order doesn't
carry meaning or when no focusable elements are affected.
Positioning and stacking¶
<div class="relative">
<img class="rounded-lg" src="soup.jpg" alt="…" width="600" height="400">
<span class="absolute top-2 end-2 rounded bg-white px-2 py-1 text-xs font-semibold">New</span>
</div>
<header class="sticky top-0 z-10 bg-white/90 backdrop-blur">…</header>
static, relative, absolute, fixed, sticky; offsets inset-0, inset-x-0,
top-4, start-4, end-2 (logical — mirror in RTL); z-0 to z-50 and z-auto,
arbitrary z-[60]. The CSS rules are exactly the plain-CSS ones: an absolute element
positions against its nearest positioned ancestor, and z-index only competes within a
stacking context. If a z-50 element still hides behind something, a parent with
opacity, transform or filter has probably created a stacking context —
this lesson
explains the rules. isolate (isolation: isolate) creates one deliberately.
Worked example: a media object with actions¶
<article class="flex items-start gap-4 rounded-lg border border-gray-200 p-4">
<img class="size-12 shrink-0 rounded-full" src="priya.jpg" alt="" width="48" height="48">
<div class="min-w-0 flex-1">
<div class="flex items-baseline gap-2">
<h3 class="truncate font-semibold">Priya Rao</h3>
<time class="shrink-0 text-xs text-gray-500" datetime="2026-09-30">2 h ago</time>
</div>
<p class="mt-1 text-sm text-gray-700">
Made this twice this week — roasting the garlic whole is the trick.
</p>
</div>
<button type="button" class="shrink-0 rounded-md px-2 py-1 text-sm hover:bg-gray-100">Reply</button>
</article>
Each class answers a layout question: the avatar and button must never shrink
(shrink-0), the middle column takes the rest (flex-1) and is allowed to be narrower than
its content (min-w-0) so the name can truncate, and name and time share a text baseline
(items-baseline).
How It Actually Works¶
Layout utilities are among the simplest in Tailwind: most compile to a single declaration
(.flex { display: flex; }, .flex-1 { flex: 1; }, .shrink-0 { flex-shrink: 0; }),
with no variables involved — there's nothing to theme about display: flex. Values that
are themeable — gap, basis, inset, top — use var(--spacing) multiples like the
spacing utilities, so the whole layout scale moves together.
The order-first utility shows a small implementation detail: it compiles to
order: -9999 rather than a small negative number, so it beats any reasonable explicit
order value.
Common mistakes¶
truncateor long content in a flex child withoutmin-w-0.flex-autowhen you wanted equal columns (flex-1), or the reverse.- Squashed icons — add
shrink-0. space-x-*in rows that wrap — usegap-*.- Raising
z-*values to fix a stacking-context problem. order-*on interactive elements, scrambling keyboard order.
Exercise¶
- Build the media-object card. Delete
min-w-0and use a very long name to see the overflow; put it back. - Make a header with a logo, a nav and a "Sign in" button, where the nav and button sit at the end, wrapping neatly on narrow screens.
- Build three pricing columns with
flex-1, then switch toflex-autowith different text lengths and describe the difference. - Overlay a "Sold out" badge on the top-end corner of a product image with
relativeandabsolute.