Automattic logo

Skill

spatial-rhythm-and-whitespace

apply premium spatial rhythm and whitespace

Covers Frontend Visual Design UX Design Design

Description

Apply the spacing, container, grid, and border-radius rhythm of premium VC-funded sites. Generous 80-160px section padding, intentional non-strict spacing scales (including 20/28/40), deliberate radius architecture (binary 0-or-pill, asymmetric interlocking, per-element variety), 40px paragraph-spacing on h2, 1px hairline dividers at 4-10% opacity. Use when layouts feel cramped, monotonous, or use "rounded-md everywhere."

SKILL.md

Spatial Rhythm and Whitespace

The way space is used separates premium sites from templates. Extracted from Cal.com, Duna, Antimetal, Cohere, AngelList, Incident, Hex, Reducto.

When to invoke

  • Sections are py-12 or py-16 across the whole page
  • Every element uses rounded-md (8px) or rounded-lg (8px)
  • Cards are tight against each other with 16px gaps
  • The h2 → p gap is default 1em line-height
  • Container width feels arbitrary
  • User says design feels "cramped" or "monotonous"

The 7 core rules

Rule 1: Border-radius is a designed system, not a default

Premium sites use different radii per element type. Generic sites use one radius everywhere.

Four radius architectures observed in case studies — pick ONE:

(A) Duna's binary system — only 0 OR 9999px (pill):

/* Sharp rectangular cards */
.card { border-radius: 0; }
/* Fully pill buttons */
.btn  { border-radius: 9999px; }
/* Nothing in between — no rounded-md 8px */

This is the most aggressive and recognizable move.

(B) Cohere's asymmetric interlocking20px on outer corners, 0 at joins:

/* Card in a 2x2 grid, top-left position */
.grid-card:nth-child(1) { border-radius: 20px 0 0 20px; }
.grid-card:nth-child(2) { border-radius: 0 20px 20px 0; }
.grid-card:nth-child(3) { border-radius: 20px 0 0 18px; }
.grid-card:nth-child(4) { border-radius: 0 20px 18px 0; }

/* Stitched "top of section" panel */
.panel-top { border-radius: 20px 20px 0 0; }
/* Stitched "bottom" */
.panel-bottom { border-radius: 0 0 18px 20px; }

Cards visually lock together like quilt tiles.

(C) Per-element variety (Hex, Cal, AngelList) — radius matches semantic role:

.btn-pill   { border-radius: 9999px; } /* primary pills */
.btn-chip   { border-radius: 30px; }   /* chips and secondary */
.card       { border-radius: 12px; }   /* most cards */
.card-large { border-radius: 20px; }   /* feature cards */
.input      { border-radius: 8px; }
.avatar     { border-radius: 50%; }
.tag        { border-radius: 2px; }    /* micro chips */
.feature    { border-radius: 40px; }   /* large hero elements */

(D) Extreme-radius for art (AngelList) — 200–300px radius creates "stadium" shapes:

.art-plate { border-radius: 300px; overflow: hidden; aspect-ratio: 2/1; }

Anti-pattern: border-radius: 8px on every card, button, input, image.

Rule 2: Section padding is 80-160px, not 48-64px

Premium sites breathe. Section vertical padding is generous:

/* Minimum acceptable */
.section { padding-block: 80px; }

/* Premium default */
.section { padding-block: 120px; }

/* Hero/marketing sections */
.section-hero { padding-block: 140px 96px; }

/* Editorial/rhythm-heavy sections */
.section-editorial { padding-block: 160px; }

Duna's observed values: 128px 40px, 140px 40px, 128px 40px 96px — vertical padding dominates, paired with fixed horizontal.

Incident / AngelList: section padding ranges 80-160px fluid.

Amplemarket: 120-200px on desktop.

Rule 3: Spacing scales include non-4-multiples

Strict 4/8/12/16 multiples are a tell. Premium sites include oddballs — 20, 28, 40, 64, 96, 128, 140.

Observed scales:

SiteSpacing scale
Duna4, 8, 12, 16, 20, 24, 40, 64, 80, 96, 128
Cal4, 8, 12, 16, 24, 28, 40
Hex4, 8, 10, 12, 16, 20, 24, 32, 40, 48, 60, 80, 120
Cohere4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96, 128, 160
Antimetal(Tailwind v4 arbitrary-multiples — w-120, calc(1120*1px))

The 20px and 28px entries break the strict-4-multiples habit. Use them for:

  • 20px: intermediate padding between "tight" (16px) and "comfortable" (24px)
  • 28px: h4 tier, card-body pairings

Anti-pattern: gap-4 p-4 m-4 (Tailwind monotone).

Rule 4: Paragraph spacing is explicit and generous

After h2, set a deliberate paragraph-spacing of 40px (Cal's observed default). Don't rely on margins from line-height.

h2 { margin-block-end: 40px; }      /* Cal's spec */
h3 { margin-block-end: 24px; }
p + p { margin-block-start: 1.25em; }

Framer's paragraphSpacing pattern (from Cal.com and Duna):

h2 { padding-block-end: 40px; }
p { padding-block-end: 20px; }

Rule 5: Container widths are deliberate, and 1200-1280px is the sweet spot

/* Most common premium width */
.container { max-width: 1280px; margin-inline: auto; padding-inline: 24px; }

/* Reducto */
.container-reducto { max-width: 1280px; }

/* Editorial/reading */
.container-prose { max-width: 720px; }

/* Feature/hero blocks */
.container-wide { max-width: 1440px; }

Outseta uses width: 88% of viewport (percent-based — more forgiving at wide screens). Antimetal has multiple: 400px, 568px, 768px, 992px, 1200px, 1536px.

Horizontal padding should scale with viewport:

.container {
  padding-inline: clamp(16px, 4vw, 80px);
}

Rule 6: Hairline dividers at 4-11% alpha, never solid

Premium sites use hairlines with LOW opacity:

/* Observed hairline tokens */
--hairline-subtle:  rgba(0, 0, 0, 0.04);     /* Duna */
--hairline-light:   rgba(0, 0, 0, 0.06);     /* Hex, most common */
--hairline-medium:  rgba(0, 0, 0, 0.10);     /* default */
--hairline-navy:    rgba(12, 38, 77, 0.04);  /* Antimetal (theme-tinted) */
--hairline-warm:    rgba(0, 45, 51, 0.10);   /* AngelList */

/* Use as 1px border */
hr { border: 0; border-top: 1px solid var(--hairline-light); }

/* Better: use as box-shadow 1px ring (common pattern) */
.card { box-shadow: 0 0 0 1px var(--hairline-light); }

/* Bottom-line shadow trick (AngelList's "shadow-b") */
.nav-item { box-shadow: 0 1px 0 #002d331a; }

Anti-pattern: border: 1px solid #e5e7eb (cold/generic).

Rule 7: Grid gaps match typographic rhythm

Gaps between cards should echo the spacing of text below them. Options:

/* Tight editorial grid (like a newspaper) — 8-12px gaps */
.grid-editorial { gap: 12px; }

/* Standard content grid — 16-24px */
.grid-cards { gap: 24px; }

/* Spacious feature grid — 32-48px */
.grid-features { gap: 40px; }

Reducto uses tight 2-16px gaps between components with generous py-16 to py-32 section padding — small gaps, big sections is a deliberate rhythm.

AngelList has tight internal content with giant section breaks.

Complete spacing system starter

:root {
  /* Spacing scale — includes non-4 multiples */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;    /* breaker */
  --space-6:  24px;
  --space-7:  28px;    /* breaker */
  --space-8:  32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;
  --space-32: 128px;
  --space-40: 160px;

  /* Section padding presets */
  --section-py-tight:    var(--space-20);   /* 80px */
  --section-py-default:  var(--space-24);   /* 96px */
  --section-py-generous: var(--space-32);   /* 128px */
  --section-py-hero:     var(--space-40);   /* 160px */

  /* Container widths */
  --container-prose:  720px;
  --container-main:   1280px;
  --container-wide:   1440px;

  /* Radius system (per-element) */
  --radius-chip:   2px;
  --radius-input:  8px;
  --radius-card:   12px;
  --radius-large:  20px;
  --radius-hero:   40px;
  --radius-pill:   9999px;

  /* Hairlines */
  --hairline: rgba(0, 0, 0, 0.06);
}

/* Layout primitives */
.container {
  max-width: var(--container-main);
  margin-inline: auto;
  padding-inline: clamp(16px, 4vw, 80px);
}

.section {
  padding-block: var(--section-py-default);
}
.section--hero      { padding-block: var(--section-py-hero) var(--space-24); }
.section--generous  { padding-block: var(--section-py-generous); }

/* Typographic rhythm */
h2 { margin-block-end: 40px; }
h3 { margin-block-end: 24px; }
p  { margin-block-end: 20px; }
p:last-child { margin-block-end: 0; }

/* Hairlines */
.divider { height: 1px; background: var(--hairline); border: 0; }
.card    { box-shadow: 0 0 0 1px var(--hairline); }

Application workflow

  1. Choose a radius architecture — binary / asymmetric / per-element / extreme — and commit to it.
  2. Upgrade section padding to 80-160px (usually +50% more than you'd default).
  3. Add 20 and 28 to your spacing scale if you're stuck in strict-4-multiples.
  4. Set explicit margin-block-end: 40px on h2 for generous paragraph spacing.
  5. Set container max-width: 1280px for main content, 720px for prose.
  6. Drop hairlines to 4-10% alpha (rarely solid gray).
  7. Tighten grid gaps to 8-24px, but increase section padding to compensate.

Anti-patterns to kill

  • rounded-md (8px) on every surface
  • py-12 as the section padding across the whole site
  • Strict Tailwind 4-multiple scale with no 20/28/40 interpolation
  • border: 1px solid #e5e7eb instead of a translucent hairline
  • max-width: 100% with no container (text blocks flow edge-to-edge at wide)
  • Monotone gap-4 between everything
  • Tight 48px section padding that makes the page feel cramped
  • Missing paragraph-spacing after h2 (text runs into prose)

Site references

PatternCase study
Binary 0 or 9999px radiusDuna
Asymmetric interlocking radiusCohere (20px on outer, 0 at joins)
Per-element radius varietyHex, Cal, AngelList
Extreme 200-300px radius art platesAngelList
128-160px section paddingDuna, Incident, Amplemarket
40px margin-block-end on h2Cal
20px + 28px in spacing scaleCal, Duna, Hex
Theme-tinted hairlinesAntimetal (navy 4%)
1280px main containerReducto, Incident, most sites
Tight 2-16px component gaps + huge section paddingReducto

© 2026 YourAI.tools. Every skill from an identity-verified publisher.

Independent catalog. Not affiliated with, endorsed by, or sponsored by Anthropic or any listed publisher. All trademarks belong to their respective owners.