Layout Patterns

Common layout patterns for building responsive, well-structured pages. These patterns solve 80% of layout challenges you'll encounter.

Page Container

Center content with max-width and horizontal padding:

// Basic container
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
  {/* Page content */}
</div>

// Narrower for content pages
<div className="max-w-3xl mx-auto px-4">
  {/* Article content */}
</div>

// Full width with padding
<div className="w-full px-4 sm:px-6 lg:px-8">
  {/* Dashboard content */}
</div>

Sidebar Layout

Fixed sidebar with scrollable main content (like this docs site):

<div className="flex min-h-screen">
  {/* Sidebar - fixed width, sticky */}
  <aside className="sticky top-0 h-screen w-64 shrink-0 overflow-y-auto border-r">
    <nav className="p-4">
      {/* Navigation links */}
    </nav>
  </aside>

  {/* Main content - flexible width */}
  <main className="flex-1 min-w-0 p-8">
    {/* Page content */}
  </main>
</div>

Key points:

  • shrink-0 - Prevents sidebar from shrinking
  • min-w-0 - Allows main content to shrink below content size
  • sticky top-0 - Keeps sidebar visible while scrolling
  • h-screen overflow-y-auto - Independent sidebar scrolling

Sticky Header Layout

<div className="min-h-screen flex flex-col">
  {/* Header - sticky at top */}
  <header className="sticky top-0 z-50 h-16 border-b bg-white/80 backdrop-blur">
    <nav className="h-full max-w-7xl mx-auto px-4 flex items-center">
      {/* Logo, nav links */}
    </nav>
  </header>

  {/* Main content - grows to fill space */}
  <main className="flex-1">
    {/* Page content */}
  </main>

  {/* Footer - at bottom */}
  <footer className="border-t py-8">
    {/* Footer content */}
  </footer>
</div>

Card Grid

Responsive grid that adapts to screen size:

// Auto-fit grid (cards stretch to fill)
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
  <Card>...</Card>
  <Card>...</Card>
  <Card>...</Card>
</div>

// Fixed columns with auto-placement
<div className="grid grid-cols-[repeat(auto-fill,minmax(300px,1fr))] gap-6">
  {/* Cards automatically wrap */}
</div>

// Masonry-like with CSS columns (for varying heights)
<div className="columns-1 sm:columns-2 lg:columns-3 gap-6 space-y-6">
  <Card>...</Card>
  <Card>...</Card>
</div>

Split Layout (50/50)

Two-column layout that stacks on mobile:

// Hero with image
<section className="grid lg:grid-cols-2 gap-8 items-center">
  <div className="space-y-4">
    <h1 className="text-4xl font-bold">Headline</h1>
    <p className="text-lg text-gray-600">Description text</p>
    <Button>Get Started</Button>
  </div>
  <div className="aspect-video bg-gray-100 rounded-lg">
    <img src="/hero.jpg" alt="" className="w-full h-full object-cover" />
  </div>
</section>

// Form beside info (reverse on mobile)
<div className="flex flex-col-reverse lg:flex-row gap-8">
  <div className="flex-1">
    {/* Form */}
  </div>
  <div className="flex-1 lg:max-w-md">
    {/* Info sidebar */}
  </div>
</div>

Centered Content

// Centered hero section
<section className="min-h-[60vh] flex items-center justify-center text-center px-4">
  <div className="max-w-2xl">
    <h1 className="text-5xl font-bold">Big Headline</h1>
    <p className="mt-4 text-xl text-gray-600">Supporting text</p>
    <div className="mt-8 flex justify-center gap-4">
      <Button>Primary</Button>
      <Button variant="outline">Secondary</Button>
    </div>
  </div>
</section>

// Login/signup form centered
<div className="min-h-screen flex items-center justify-center p-4">
  <Card className="w-full max-w-md">
    {/* Form content */}
  </Card>
</div>

List with Actions

// List item with content and actions
<ul className="divide-y">
  {items.map(item => (
    <li key={item.id} className="flex items-center justify-between py-4">
      <div className="flex items-center gap-4 min-w-0">
        <Avatar>{item.avatar}</Avatar>
        <div className="min-w-0">
          <p className="font-medium truncate">{item.name}</p>
          <p className="text-sm text-gray-500 truncate">{item.email}</p>
        </div>
      </div>
      <div className="flex items-center gap-2 ml-4">
        <Button size="sm" variant="ghost">Edit</Button>
        <Button size="sm" variant="ghost">Delete</Button>
      </div>
    </li>
  ))}
</ul>

Note: min-w-0 and truncate prevent long text from breaking layout.

Dashboard Layout

<div className="min-h-screen bg-gray-50">
  {/* Top navbar */}
  <header className="sticky top-0 z-40 h-16 bg-white border-b">
    {/* ... */}
  </header>

  <div className="flex">
    {/* Sidebar navigation */}
    <aside className="sticky top-16 h-[calc(100vh-4rem)] w-64 border-r bg-white">
      <nav className="p-4 space-y-1">
        {/* Nav items */}
      </nav>
    </aside>

    {/* Main content area */}
    <main className="flex-1 p-6">
      {/* Stats row */}
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
        <Card>Stat 1</Card>
        <Card>Stat 2</Card>
        <Card>Stat 3</Card>
        <Card>Stat 4</Card>
      </div>

      {/* Two column layout */}
      <div className="grid lg:grid-cols-3 gap-6">
        <Card className="lg:col-span-2">Main chart</Card>
        <Card>Recent activity</Card>
      </div>
    </main>
  </div>
</div>

Responsive Tips

Mobile First

Start with mobile layout, add complexity at larger breakpoints.grid-cols-1 md:grid-cols-2 lg:grid-cols-3

Hide/Show

Hide elements at certain breakpoints.hidden md:block or md:hidden

Stack → Row

Stack vertically on mobile, horizontal on desktop.flex flex-col md:flex-row

Adjust Spacing

Use smaller spacing on mobile.p-4 md:p-6 lg:p-8