- **Component Creation Guide:** Document best practices for creating reusable, accessible components using CVA patterns. Includes guidance on when to compose vs create, decision trees, templates, prop design, testing checklists, and real-world examples. - **Design System README:** Introduce an organized structure for the design system documentation with quick navigation, learning paths, and reference links to key topics. Includes paths for quick starts, layouts, components, forms, and AI setup.
13 KiB
Layout Patterns
Master the 5 essential layouts that cover 80% of all interface needs. Learn when to use Grid vs Flex, and build responsive, consistent layouts every time.
Table of Contents
- Grid vs Flex Decision Tree
- The 5 Essential Patterns
- Responsive Strategies
- Common Mistakes
- Advanced Patterns
Grid vs Flex Decision Tree
Use this flowchart to choose between Grid and Flex:
┌─────────────────────────────────────┐
│ Need equal-width columns? │
│ (e.g., 3 cards of same width) │
└──────────┬─YES──────────┬─NO────────┘
│ │
▼ ▼
USE GRID Need 2D layout?
(rows + columns)
│
┌────┴────┐
│YES │NO
▼ ▼
USE GRID USE FLEX
Quick Rules
| Scenario | Solution |
|---|---|
| Equal-width columns | Grid (grid grid-cols-3) |
| Flexible item sizes | Flex (flex gap-4) |
| 2D layout (rows + cols) | Grid (grid grid-cols-2 grid-rows-3) |
| 1D layout (row OR col) | Flex (flex or flex flex-col) |
| Card grid | Grid (grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3) |
| Navbar items | Flex (flex items-center gap-4) |
| Sidebar + Content | Flex (flex gap-6) |
| Form fields | Flex column (flex flex-col gap-4 or space-y-4) |
The 5 Essential Patterns
These 5 patterns cover 80% of all layout needs. Master these first.
1. Page Container Pattern
Use case: Standard page layout with readable content width
<div className="container mx-auto px-4 py-8">
<div className="max-w-4xl mx-auto space-y-6">
<h1 className="text-3xl font-bold">Page Title</h1>
<Card>
<CardHeader>
<CardTitle>Section Title</CardTitle>
</CardHeader>
<CardContent>
Page content goes here
</CardContent>
</Card>
</div>
</div>
Key Features:
container- Responsive container with max-widthmx-auto- Center horizontallypx-4- Horizontal padding (mobile-friendly)py-8- Vertical paddingmax-w-4xl- Constrain content width for readabilityspace-y-6- Vertical spacing between children
When to use:
- Blog posts
- Documentation pages
- Settings pages
- Any page with readable content
2. Dashboard Grid Pattern
Use case: Responsive card grid that adapts to screen size
<div className="container mx-auto px-4 py-8">
<h1 className="text-3xl font-bold mb-6">Dashboard</h1>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{items.map(item => (
<Card key={item.id}>
<CardHeader>
<CardTitle>{item.title}</CardTitle>
<CardDescription>{item.description}</CardDescription>
</CardHeader>
<CardContent>
<p className="text-2xl font-bold">{item.value}</p>
</CardContent>
</Card>
))}
</div>
</div>
Responsive behavior:
- Mobile (
< 768px): 1 column - Tablet (
≥ 768px): 2 columns - Desktop (
≥ 1024px): 3 columns
Key Features:
grid- Use CSS Gridgrid-cols-1- Default: 1 column (mobile-first)md:grid-cols-2- 2 columns on tabletlg:grid-cols-3- 3 columns on desktopgap-6- Consistent spacing between items
When to use:
- Dashboards
- Product grids
- Image galleries
- Card collections
3. Form Layout Pattern
Use case: Centered form with constrained width
<div className="container mx-auto px-4 py-8">
<Card className="max-w-md mx-auto">
<CardHeader>
<CardTitle>Login</CardTitle>
<CardDescription>Enter your credentials to continue</CardDescription>
</CardHeader>
<CardContent>
<form className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="you@example.com" />
</div>
<div className="space-y-2">
<Label htmlFor="password">Password</Label>
<Input id="password" type="password" />
</div>
<Button className="w-full">Sign In</Button>
</form>
</CardContent>
</Card>
</div>
Key Features:
max-w-md- Constrain form width (448px max)mx-auto- Center the formspace-y-4- Vertical spacing between fieldsw-full- Full-width button
Form width guidelines:
- Short forms (login, signup):
max-w-md(448px) - Medium forms (profile, settings):
max-w-lg(512px) - Long forms (checkout):
max-w-2xl(672px)
When to use:
- Login/signup forms
- Contact forms
- Settings forms
- Any single-column form
4. Sidebar Layout Pattern
Use case: Sidebar navigation with main content area
<div className="flex min-h-screen">
{/* Sidebar */}
<aside className="w-64 border-r bg-muted/40 p-6">
<nav className="space-y-2">
<a href="#" className="block rounded-lg px-3 py-2 text-sm hover:bg-accent">
Dashboard
</a>
<a href="#" className="block rounded-lg px-3 py-2 text-sm hover:bg-accent">
Settings
</a>
</nav>
</aside>
{/* Main Content */}
<main className="flex-1 p-6">
<div className="max-w-4xl mx-auto">
<h1 className="text-3xl font-bold mb-6">Page Title</h1>
{/* Content */}
</div>
</main>
</div>
Key Features:
flex- Horizontal layoutw-64- Fixed sidebar width (256px)flex-1- Main content takes remaining spacemin-h-screen- Full viewport heightborder-r- Visual separator
Responsive strategy:
// Mobile: Collapsible sidebar
<div className="flex min-h-screen">
{/* Sidebar - hidden on mobile */}
<aside className="hidden lg:block w-64 border-r p-6">
{/* Sidebar content */}
</aside>
{/* Main content - full width on mobile */}
<main className="flex-1 p-4 lg:p-6">
{/* Content */}
</main>
</div>
// Add mobile menu button
<Button size="icon" className="lg:hidden">
<Menu className="h-6 w-6" />
</Button>
When to use:
- Admin dashboards
- Settings pages
- Documentation sites
- Apps with persistent navigation
5. Centered Content Pattern
Use case: Single-column content with optimal reading width
<div className="container mx-auto px-4 py-8">
<article className="max-w-2xl mx-auto">
<h1 className="text-4xl font-bold mb-4">Article Title</h1>
<p className="text-muted-foreground mb-8">Published on Nov 2, 2025</p>
<div className="prose prose-lg">
<p>Article content with optimal line length for reading...</p>
<p>More content...</p>
</div>
</article>
</div>
Key Features:
max-w-2xl- Optimal reading width (672px)mx-auto- Center contentprose- Typography styles (if using @tailwindcss/typography)
Width recommendations:
- Articles/Blogs:
max-w-2xl(672px) - Documentation:
max-w-3xl(768px) - Landing pages:
max-w-4xl(896px) or wider - Forms:
max-w-md(448px)
When to use:
- Blog posts
- Articles
- Documentation
- Long-form content
Responsive Strategies
Mobile-First Approach
Always start with mobile layout, then enhance for larger screens:
// ✅ CORRECT - Mobile first
<div className="
p-4 // Mobile: 16px padding
sm:p-6 // Tablet: 24px padding
lg:p-8 // Desktop: 32px padding
">
<div className="
grid
grid-cols-1 // Mobile: 1 column
sm:grid-cols-2 // Tablet: 2 columns
lg:grid-cols-3 // Desktop: 3 columns
gap-4
">
{/* Items */}
</div>
</div>
// ❌ WRONG - Desktop first
<div className="p-8 md:p-6 sm:p-4"> // Don't do this
Breakpoints
| Breakpoint | Min Width | Typical Use |
|---|---|---|
sm: |
640px | Large phones, small tablets |
md: |
768px | Tablets |
lg: |
1024px | Laptops, desktops |
xl: |
1280px | Large desktops |
2xl: |
1536px | Extra large screens |
Responsive Grid Columns
// 1→2→3→4 progression (common)
grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4
// 1→2→3 progression (most common)
grid-cols-1 md:grid-cols-2 lg:grid-cols-3
// 1→2 progression (simple)
grid-cols-1 md:grid-cols-2
// 1→3 progression (skip 2)
grid-cols-1 lg:grid-cols-3
Responsive Text
// Heading sizes
<h1 className="
text-2xl sm:text-3xl lg:text-4xl
font-bold
">
Responsive Title
</h1>
// Body text (usually doesn't need responsive sizes)
<p className="text-base">
Body text stays consistent
</p>
Common Mistakes
❌ Mistake 1: Using Margins Instead of Gap
// ❌ WRONG - Children have margins
<div className="flex">
<div className="mr-4">Item 1</div>
<div className="mr-4">Item 2</div>
<div>Item 3</div> {/* Last one has no margin */}
</div>
// ✅ CORRECT - Parent controls spacing
<div className="flex gap-4">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
❌ Mistake 2: Fixed Widths Instead of Responsive
// ❌ WRONG - Fixed width, not responsive
<div className="w-[800px]">
Content
</div>
// ✅ CORRECT - Responsive width
<div className="w-full max-w-4xl mx-auto px-4">
Content
</div>
❌ Mistake 3: Not Using Container
// ❌ WRONG - Content touches edges on large screens
<div className="px-4">
Content spans full width on 4K screens
</div>
// ✅ CORRECT - Container constrains width
<div className="container mx-auto px-4">
Content has maximum width
</div>
❌ Mistake 4: Desktop-First Responsive
// ❌ WRONG - Desktop first
<div className="p-8 lg:p-6 md:p-4">
// ✅ CORRECT - Mobile first
<div className="p-4 md:p-6 lg:p-8">
❌ Mistake 5: Using Flex for Equal Columns
// ❌ WRONG - Flex doesn't guarantee equal widths
<div className="flex gap-4">
<div className="flex-1">Col 1</div>
<div className="flex-1">Col 2</div>
<div className="flex-1">Col 3</div>
</div>
// ✅ CORRECT - Grid ensures equal widths
<div className="grid grid-cols-3 gap-4">
<div>Col 1</div>
<div>Col 2</div>
<div>Col 3</div>
</div>
Advanced Patterns
Asymmetric Grid
// 2/3 - 1/3 split
<div className="grid grid-cols-3 gap-6">
<div className="col-span-2">
Main content (2/3 width)
</div>
<div className="col-span-1">
Sidebar (1/3 width)
</div>
</div>
Auto-fit Grid (Flexible columns)
// Columns adjust based on available space
<div className="grid grid-cols-[repeat(auto-fit,minmax(300px,1fr))] gap-6">
<Card>Item 1</Card>
<Card>Item 2</Card>
<Card>Item 3</Card>
{/* Adds as many columns as fit */}
</div>
Sticky Sidebar
<div className="flex gap-6">
<aside className="sticky top-6 h-fit w-64">
{/* Stays in view while scrolling */}
</aside>
<main className="flex-1">
{/* Scrollable content */}
</main>
</div>
Full-height Layout
<div className="flex flex-col min-h-screen">
<header className="h-16 border-b">Header</header>
<main className="flex-1">Flexible content</main>
<footer className="h-16 border-t">Footer</footer>
</div>
Layout Checklist
Before implementing a layout, ask:
- Responsive? Does it work on mobile, tablet, desktop?
- Container? Is content constrained on large screens?
- Spacing? Using
gaporspace-y, not margins on children? - Mobile-first? Starting with mobile layout?
- Semantic? Using appropriate HTML tags (main, aside, nav)?
- Accessible? Proper heading hierarchy, skip links?
Quick Reference
Grid Cheat Sheet
// Basic grid
grid grid-cols-3 gap-6
// Responsive grid
grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6
// Asymmetric grid
grid grid-cols-3 gap-6
<div className="col-span-2">...</div>
// Auto-fit grid
grid grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-6
Flex Cheat Sheet
// Horizontal flex
flex gap-4
// Vertical flex
flex flex-col gap-4
// Center items
flex items-center justify-center
// Space between
flex items-center justify-between
// Wrap items
flex flex-wrap gap-4
Container Cheat Sheet
// Standard container
container mx-auto px-4 py-8
// Constrained width
max-w-4xl mx-auto px-4
// Full width
w-full px-4
Next Steps
- Practice: Build pages using the 5 essential patterns
- Explore: Interactive layout examples
- Deep Dive: Spacing Philosophy
- Reference: Quick Reference Tables
Related Documentation:
- Spacing Philosophy - When to use margin vs padding vs gap
- Foundations - Spacing tokens and scale
- Quick Start - Essential patterns
Last Updated: November 2, 2025