Layouts

Composable primitives for page structure. Container, Grid, Stack, Cluster, Split, Sidebar, and Center — combine them to build any layout without writing custom CSS.


Container

Centers content with a max-width and horizontal padding.

--narrow 640px
default 960px
--wide 1280px
<div style="display: flex; flex-direction: column; gap: var(--space-3); width: 100%;">
<div class="Layout-container Layout-container--narrow" style="background: var(--accent-s); padding: var(--space-3); border-radius: var(--r-s); border: 1px dashed var(--accent);">
<code style="font-size: .75rem; color: var(--accent);">--narrow</code> <span style="color: var(--fg-3); font-size: .8rem;">640px</span>
</div>
<div class="Layout-container" style="background: var(--bg-s); padding: var(--space-3); border-radius: var(--r-s); border: 1px dashed var(--bd-s);">
<code style="font-size: .75rem;">default</code> <span style="color: var(--fg-3); font-size: .8rem;">960px</span>
</div>
<div class="Layout-container Layout-container--wide" style="background: var(--bg-s); padding: var(--space-3); border-radius: var(--r-s); border: 1px dashed var(--bd-s);">
<code style="font-size: .75rem;">--wide</code> <span style="color: var(--fg-3); font-size: .8rem;">1280px</span>
</div>
</div>
<div class="Layout-container">...</div>
<div class="Layout-container Layout-container--narrow">...</div>
<div class="Layout-container Layout-container--wide">...</div>

Grid

A 24-column fluid grid. All columns collapse to full-width below 768px. Use Layout-col-{n}@md for responsive spans. The 24-column system gives finer control — thirds (8-col), halves (12-col), quarters (6-col), and asymmetric splits like 16/8 or 18/6.

8
8
8
<div class="Layout-grid" style="width: 100%;">
<div class="Layout-col-8" style="background: var(--accent); color: white; padding: var(--space-3); border-radius: var(--r-s); text-align: center; font-weight: 600;">8</div>
<div class="Layout-col-8" style="background: var(--accent); color: white; padding: var(--space-3); border-radius: var(--r-s); text-align: center; font-weight: 600;">8</div>
<div class="Layout-col-8" style="background: var(--accent); color: white; padding: var(--space-3); border-radius: var(--r-s); text-align: center; font-weight: 600;">8</div>
</div>
16 — Main
8 — Side
<div class="Layout-grid" style="width: 100%;">
<div class="Layout-col-16" style="background: oklch(55% 0.15 270); color: white; padding: var(--space-4); border-radius: var(--r-s); font-weight: 600;">16 — Main</div>
<div class="Layout-col-8" style="background: oklch(75% 0.08 270); padding: var(--space-4); border-radius: var(--r-s);">8 — Side</div>
</div>
<div class="Layout-grid">
    <div class="Layout-col-16">Main content</div>
    <div class="Layout-col-8">Sidebar</div>
</div>

<!-- Responsive: full on mobile, halves on tablet+ -->
<div class="Layout-grid">
    <div class="Layout-col-24 Layout-col-12@md">Left</div>
    <div class="Layout-col-24 Layout-col-12@md">Right</div>
</div>

Stack

Vertical flow with consistent gap. The most-used layout primitive.

Tight · 8px
Default · 16px
Loose · 32px
<div style="display: flex; gap: var(--space-8); align-items: flex-start;">
<div style="text-align: center;">
<div style="font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-4); margin-bottom: var(--space-2);">Tight · 8px</div>
<div class="Layout-stack Layout-stack--tight" style="width: 80px;">
<div style="background: var(--accent); height: 24px; border-radius: var(--r-s);"></div>
<div style="background: var(--accent); height: 24px; border-radius: var(--r-s);"></div>
<div style="background: var(--accent); height: 24px; border-radius: var(--r-s);"></div>
</div>
</div>
<div style="text-align: center;">
<div style="font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-4); margin-bottom: var(--space-2);">Default · 16px</div>
<div class="Layout-stack" style="width: 80px;">
<div style="background: var(--accent); height: 24px; border-radius: var(--r-s);"></div>
<div style="background: var(--accent); height: 24px; border-radius: var(--r-s);"></div>
<div style="background: var(--accent); height: 24px; border-radius: var(--r-s);"></div>
</div>
</div>
<div style="text-align: center;">
<div style="font-size: .7rem; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-4); margin-bottom: var(--space-2);">Loose · 32px</div>
<div class="Layout-stack Layout-stack--loose" style="width: 80px;">
<div style="background: var(--accent); height: 24px; border-radius: var(--r-s);"></div>
<div style="background: var(--accent); height: 24px; border-radius: var(--r-s);"></div>
<div style="background: var(--accent); height: 24px; border-radius: var(--r-s);"></div>
</div>
</div>
</div>
<div class="Layout-stack">...</div>
<div class="Layout-stack Layout-stack--tight">...</div>
<div class="Layout-stack Layout-stack--loose">...</div>

Cluster

Horizontal grouping with wrapping. For tags, buttons, inline elements.

Design Development Product Research Strategy Engineering
<div class="Layout-cluster">
<span class="Badge Badge--primary">Design</span>
<span class="Badge">Development</span>
<span class="Badge">Product</span>
<span class="Badge">Research</span>
<span class="Badge">Strategy</span>
<span class="Badge">Engineering</span>
</div>
<div class="Layout-cluster">
    <span class="Badge">Tag</span>
    <span class="Badge">Tag</span>
    ...
</div>

Split

Push items to opposite ends of a row. Headers, footers, toolbars.

Page Title
<div class="Layout-split" style="width: 100%; background: var(--bg-s); padding: var(--space-3) var(--space-4); border-radius: var(--r-s);">
<span style="font-weight: 600;">Page Title</span>
<button class="Button Button--primary Button--small">Action</button>
</div>
<div class="Layout-split">
    <h1>Title</h1>
    <button class="Button">Action</button>
</div>

Fixed-width sidebar with fluid main area. Stacks on mobile. Use --right to flip.

Main Content
Fluid width, fills remaining space
<div class="Layout-sidebar" style="width: 100%;">
<aside style="background: var(--bg-m); padding: var(--space-4); border-radius: var(--r-s);">
<strong style="font-size: .85rem;">Sidebar</strong>
<div style="color: var(--fg-3); font-size: .75rem; margin-top: var(--space-1);">240px fixed</div>
</aside>
<main style="background: var(--bg-s); padding: var(--space-4); border-radius: var(--r-s);">
<strong style="font-size: .85rem;">Main Content</strong>
<div style="color: var(--fg-3); font-size: .75rem; margin-top: var(--space-1);">Fluid width, fills remaining space</div>
</main>
</div>
<div class="Layout-sidebar">
    <aside>Navigation</aside>
    <main>Content</main>
</div>

<!-- Sidebar on right -->
<div class="Layout-sidebar Layout-sidebar--right">
    <main>Content</main>
    <aside>Sidebar</aside>
</div>

Center

Vertical and horizontal centering. Empty states, loading screens.

📭
Nothing here yet
Create your first item to get started.
<div class="Layout-center" style="height: 160px; width: 100%; background: var(--bg-s); border-radius: var(--r-s);">
<div style="text-align: center;">
<div style="font-size: 1.5rem; margin-bottom: var(--space-2);">📭</div>
<div style="font-weight: 600; font-size: .9rem;">Nothing here yet</div>
<div style="color: var(--fg-3); font-size: .8rem;">Create your first item to get started.</div>
</div>
</div>
<div class="Layout-center" style="min-height: 300px;">
    <div>Centered content</div>
</div>

Composition

These primitives are designed to nest. A typical page:

<div class="Layout-container">
    <div class="Layout-stack Layout-stack--loose">

        <header class="Layout-split">
            <h1>Dashboard</h1>
            <button class="Button Button--primary">New</button>
        </header>

        <div class="Layout-sidebar">
            <aside class="Layout-stack">
                <!-- Nav links -->
            </aside>
            <main class="Layout-stack">
                <div class="Layout-grid">
                    <div class="Layout-col-8">Stat card</div>
                    <div class="Layout-col-8">Stat card</div>
                    <div class="Layout-col-8">Stat card</div>
                </div>
                <!-- Content -->
            </main>
        </div>

    </div>
</div>

API Reference

Class Description
.Layout-container Centered container, 960px max-width
.Layout-container--narrow 640px max-width
.Layout-container--wide 1280px max-width
.Layout-grid 24-column fluid grid
.Layout-col-{1-24} Column span
.Layout-col-{1-24}@md Column span at 768px+
.Layout-stack Vertical flow, 16px gap
.Layout-stack--tight 8px gap
.Layout-stack--loose 32px gap
.Layout-cluster Horizontal wrapping group
.Layout-split Space-between row
.Layout-sidebar Sidebar (240px) + fluid main
.Layout-sidebar--right Sidebar on the right
.Layout-center Vertical + horizontal centering

Best Practices

Do

  • Start with Container — Wrap page content in Layout-container to constrain width and center the layout
  • Use Stack as your default — Most vertical arrangements should use Layout-stack rather than custom margins
  • Compose primitives — Nest Grid inside Stack inside Container; these are building blocks, not standalone solutions
  • Use responsive column classes — Apply Layout-col-24 Layout-col-12@md so layouts collapse gracefully on mobile
  • Choose the right gap — Use --tight for related items (form fields), default for sections, --loose for page-level spacing

Don’t

  • Add custom margins between layout children — Let the layout primitive’s gap handle spacing
  • Use Grid for simple vertical stacking — A 1-column grid is just a Stack; use the simpler primitive
  • Hardcode widths on grid columns — Use Layout-col-{n} classes instead of inline width styles
  • Nest grids deeply — More than two levels of Grid nesting becomes hard to maintain; flatten with Stack or Split
  • Forget the Container — Without it, content stretches edge-to-edge on wide screens and becomes unreadable

CSS Reference

/* ── Container ── */
.Layout-container {
  width: 100%;
  max-width: 960px;
  margin-inline: auto;
  padding-inline: var(--space-4);
}

.Layout-container--narrow {
  max-width: 640px;
}

.Layout-container--wide {
  max-width: 1280px;
}

/* ── Grid (24-column) ── */
.Layout-grid {
  display: grid;
  grid-template-columns: repeat(24, 1fr);
  gap: var(--space-4);
}

.Layout-col-1  { grid-column: span 1; }
.Layout-col-2  { grid-column: span 2; }
.Layout-col-3  { grid-column: span 3; }
.Layout-col-4  { grid-column: span 4; }
.Layout-col-5  { grid-column: span 5; }
.Layout-col-6  { grid-column: span 6; }  /* Quarter */
.Layout-col-7  { grid-column: span 7; }
.Layout-col-8  { grid-column: span 8; }  /* Third */
.Layout-col-9  { grid-column: span 9; }
.Layout-col-10 { grid-column: span 10; }
.Layout-col-11 { grid-column: span 11; }
.Layout-col-12 { grid-column: span 12; } /* Half */
.Layout-col-13 { grid-column: span 13; }
.Layout-col-14 { grid-column: span 14; }
.Layout-col-15 { grid-column: span 15; }
.Layout-col-16 { grid-column: span 16; } /* Two-thirds */
.Layout-col-17 { grid-column: span 17; }
.Layout-col-18 { grid-column: span 18; } /* Three-quarters */
.Layout-col-19 { grid-column: span 19; }
.Layout-col-20 { grid-column: span 20; }
.Layout-col-21 { grid-column: span 21; }
.Layout-col-22 { grid-column: span 22; }
.Layout-col-23 { grid-column: span 23; }
.Layout-col-24 { grid-column: span 24; } /* Full */

@media (min-width: 768px) {
  .Layout-col-1\@md  { grid-column: span 1; }
  /* ... spans 2-23 ... */
  .Layout-col-12\@md { grid-column: span 12; }
  .Layout-col-24\@md { grid-column: span 24; }
}

/* ── Stack ── */
.Layout-stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.Layout-stack--tight {
  gap: var(--space-2);
}

.Layout-stack--loose {
  gap: var(--space-8);
}

/* ── Cluster ── */
.Layout-cluster {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  align-items: center;
}

/* ── Split ── */
.Layout-split {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-4);
}

/* ── Sidebar ── */
.Layout-sidebar {
  display: flex;
  gap: var(--space-4);
}

.Layout-sidebar > aside {
  flex: 0 0 240px;
}

.Layout-sidebar > main {
  flex: 1 1 0%;
  min-width: 0;
}

.Layout-sidebar--right {
  flex-direction: row-reverse;
}

@media (max-width: 767px) {
  .Layout-sidebar {
    flex-direction: column;
  }

  .Layout-sidebar > aside {
    flex: none;
  }
}

/* ── Center ── */
.Layout-center {
  display: flex;
  align-items: center;
  justify-content: center;
}