On this page
Flexbox and Grid with Tailwind
Flexbox and Grid with Tailwind
Layout is where Tailwind's utility-first approach shines most clearly. Instead of writing display: flex; align-items: center; justify-content: space-between in a stylesheet, you write flex items-center justify-between directly on the element. The mapping is immediate and readable.
Flexbox utilities
Every CSS flexbox property has a direct Tailwind equivalent.
Enabling flexbox
<div class="flex">...</div> <!-- display: flex -->
<div class="inline-flex">...</div> <!-- display: inline-flex -->Direction
<div class="flex flex-row">...</div> <!-- default: left to right -->
<div class="flex flex-col">...</div> <!-- top to bottom (most common) -->
<div class="flex flex-row-reverse">...</div> <!-- right to left -->
<div class="flex flex-col-reverse">...</div> <!-- bottom to top -->Alignment
justify-content controls the main axis (horizontal in a row, vertical in a column). align-items controls the cross axis.
<!-- justify-content -->
<div class="flex justify-start">...</div> /* flex-start */
<div class="flex justify-center">...</div> /* center */
<div class="flex justify-end">...</div> /* flex-end */
<div class="flex justify-between">...</div> /* space-between */
<div class="flex justify-around">...</div> /* space-around */
<div class="flex justify-evenly">...</div> /* space-evenly */
<!-- align-items -->
<div class="flex items-start">...</div> /* flex-start */
<div class="flex items-center">...</div> /* center */
<div class="flex items-end">...</div> /* flex-end */
<div class="flex items-stretch">...</div> /* stretch (default) */
<div class="flex items-baseline">...</div> /* baseline */Wrapping and gap
<!-- Wrap: children move to next line when they overflow -->
<div class="flex flex-wrap gap-4">
<div class="w-32">Card 1</div>
<div class="w-32">Card 2</div>
<div class="w-32">Card 3</div>
<!-- Cards wrap to next line when container is too narrow -->
</div>
<!-- Gap: space between flex/grid items -->
<div class="flex gap-4">...</div> /* 1rem gap on both axes */
<div class="flex gap-x-4 gap-y-2">...</div> /* different axes */Flex grow, shrink, and basis
<!-- flex-1: item grows and shrinks equally, ignoring initial size -->
<div class="flex gap-4">
<div class="flex-1 bg-indigo-100 p-4">Grows</div>
<div class="flex-1 bg-purple-100 p-4">Grows equally</div>
<div class="w-48 shrink-0 bg-gray-100 p-4">Fixed width, never shrinks</div>
</div>
<!-- flex-none: don't grow or shrink (shrink-0 equivalent but also no grow) -->
<img class="flex-none w-16 h-16 rounded-full" src="/avatar.jpg" alt="Avatar" />
<!-- Order: visually reorder flex children -->
<div class="flex">
<div class="order-3">Shows third</div>
<div class="order-1">Shows first</div>
<div class="order-2">Shows second</div>
</div>Practical flex pattern: media object
The media object pattern (icon/image left, text right) is one of the most common UI patterns:
<div class="flex items-start gap-4 p-4 bg-white rounded-xl border border-gray-100">
<!-- Icon on the left, never shrinks -->
<div class="shrink-0 w-12 h-12 rounded-full bg-indigo-100 flex items-center justify-center">
<svg class="w-6 h-6 text-indigo-600" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/>
</svg>
</div>
<!-- Text grows to fill available space -->
<div class="flex-1 min-w-0">
<p class="font-semibold text-gray-900 truncate">Alice Johnson</p>
<p class="text-sm text-gray-500">Replied to your comment</p>
<p class="mt-1 text-sm text-gray-700">"Great article! The examples are very clear."</p>
</div>
<!-- Timestamp, pinned right -->
<time class="shrink-0 text-xs text-gray-400">2h ago</time>
</div>CSS Grid utilities
CSS Grid is for two-dimensional layouts — rows AND columns simultaneously.
Enabling grid and defining columns
<div class="grid grid-cols-3">...</div> /* 3 equal columns */
<div class="grid grid-cols-4 gap-6">...</div> /* 4 columns with gap */
<!-- Responsive column count (most common pattern) -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
...
</div>Column spanning
<!-- col-span-N: item occupies N columns -->
<div class="grid grid-cols-6 gap-4">
<div class="col-span-4 bg-blue-100 p-4">Main content (4 columns)</div>
<div class="col-span-2 bg-gray-100 p-4">Sidebar (2 columns)</div>
</div>
<!-- col-span-full: item spans all columns -->
<div class="grid grid-cols-3 gap-4">
<div class="col-span-full bg-indigo-100 p-4">Full-width header</div>
<div class="bg-white p-4">Card 1</div>
<div class="bg-white p-4">Card 2</div>
<div class="bg-white p-4">Card 3</div>
</div>Row spanning and row definition
<!-- row-span-N: item occupies N rows -->
<div class="grid grid-cols-2 grid-rows-2 gap-4 h-64">
<div class="row-span-2 bg-indigo-500 p-4 text-white">Tall left panel</div>
<div class="bg-purple-300 p-4">Top right</div>
<div class="bg-purple-200 p-4">Bottom right</div>
</div>Auto-fit responsive grids
Tailwind v4 supports arbitrary values for grid templates. For a self-wrapping grid where columns size automatically:
<!-- Repeating auto-fit grid: items fill the container and wrap -->
<div class="grid gap-6 [grid-template-columns:repeat(auto-fit,minmax(280px,1fr))]">
<div class="bg-white rounded-xl p-6 shadow">Card 1</div>
<div class="bg-white rounded-xl p-6 shadow">Card 2</div>
<div class="bg-white rounded-xl p-6 shadow">Card 3</div>
<div class="bg-white rounded-xl p-6 shadow">Card 4</div>
</div>Container queries (Tailwind v4)
Container queries let a component respond to the size of its parent container rather than the viewport. This is perfect for components that appear in different contexts (sidebar, main column, modal).
<!-- 1. Mark the parent as a container -->
<div class="@container">
<!-- 2. Use @sm:, @md:, @lg: on the child -->
<div class="grid grid-cols-1 @sm:grid-cols-2 @lg:grid-cols-3 gap-4">
<div class="bg-white p-4 rounded-lg shadow">Card</div>
<div class="bg-white p-4 rounded-lg shadow">Card</div>
<div class="bg-white p-4 rounded-lg shadow">Card</div>
</div>
</div>When the .@container div is 400px wide, the grid shows 1 column. When it's 640px wide, it shows 2 columns — regardless of the viewport width.
Holy Grail layout with Grid
The "holy grail" layout (header, two sidebars, main content, footer) is trivial with CSS Grid:
<div class="grid grid-cols-[220px_1fr_180px] grid-rows-[auto_1fr_auto] min-h-screen">
<header class="col-span-3 bg-white border-b border-gray-200 px-6 py-4 flex items-center">
<span class="font-bold text-lg">Logo</span>
</header>
<aside class="bg-gray-50 border-r border-gray-200 p-4">
<nav>Left Sidebar</nav>
</aside>
<main class="p-6 overflow-auto">
Main Content
</main>
<aside class="bg-gray-50 border-l border-gray-200 p-4">
Right Sidebar
</aside>
<footer class="col-span-3 bg-white border-t border-gray-200 px-6 py-4 text-sm text-gray-500">
Footer
</footer>
</div>Practice
- Build a dashboard sidebar layout: fixed sidebar (w-64) on the left and a scrollable main content area on the right using
flex. - Create a photo gallery using
grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2with square image cells usingaspect-square. - Wrap the gallery in a
@containerand replace the viewport breakpoints with@sm:grid-cols-2 @lg:grid-cols-4.
<!-- Responsive navigation: logo left, links center, actions right -->
<nav class="flex items-center justify-between px-6 py-4 bg-white border-b border-gray-100 shadow-sm">
<!-- Logo -->
<a href="/" class="text-xl font-bold text-indigo-600 tracking-tight">
MyApp
</a>
<!-- Center links (hidden on mobile) -->
<ul class="hidden md:flex items-center gap-6 list-none m-0 p-0">
<li><a href="/features" class="text-sm text-gray-600 hover:text-indigo-600 transition-colors">Features</a></li>
<li><a href="/pricing" class="text-sm text-gray-600 hover:text-indigo-600 transition-colors">Pricing</a></li>
<li><a href="/docs" class="text-sm text-gray-600 hover:text-indigo-600 transition-colors">Docs</a></li>
</ul>
<!-- Right side actions -->
<div class="flex items-center gap-3">
<a href="/login" class="text-sm font-medium text-gray-700 hover:text-indigo-600 transition-colors">
Sign in
</a>
<a href="/signup" class="bg-indigo-600 hover:bg-indigo-700 text-white text-sm font-semibold px-4 py-2 rounded-lg transition-colors">
Get started
</a>
</div>
</nav>
Sign in to track your progress