Skip to content
Visual craftLesson 3 of 6Beginner13 min

Spacing & rhythm

Consistent spacing on a base unit (usually 4 or 8px) gives a layout vertical rhythm. Ad-hoc margins are the most common reason a screen feels off.

Kept on this device only.

In one line: pick a base unit — usually 4 or 8px — and make every gap, pad, and margin a multiple of it; that single constraint gives a layout an even vertical rhythm and quietly fixes the "this feels off but I can't say why" screen.

What it is

Spacing is the empty space between and around elements: the gap below a heading, the padding inside a card, the margin between rows. A base unit is the smallest step you allow — commonly 4px or 8px. A spacing scale is the short, fixed set of multiples you build from it: 4, 8, 12, 16, 24, 32. Vertical rhythm is what you get when every vertical gap on the screen lands on that scale — distances relate to each other instead of being random.

The discipline is subtractive. Instead of reaching for whatever number looks right in the moment (margin: 13px), you choose from a handful of allowed steps. The constraint is the feature: fewer choices, more consistency.

Why it matters

Ad-hoc spacing is the single most common reason a competent layout still feels amateur. Each individual 7px or 22px looks fine in isolation, but stacked together the gaps don't relate, and the eye reads the irregularity as sloppiness long before anyone can name it.

A base-unit scale removes the decision entirely. Spacing becomes a vocabulary of a few named steps rather than an open field of pixels, reviews stop arguing about 14 vs 16, and the whole product picks up a calm, deliberate rhythm for free.

See it

Live demo
Tweak it2
Switch off the consistent scale to feel how ad-hoc spacing breaks a layout's rhythm.

Switch off the consistent scale toggle and watch the same card fall apart: the gaps stop relating to each other and the stack starts to feel jittery, even though nothing else changed. Flip the base between 4 and 8 to feel how a larger unit reads as airier and more generous. The mono caption names the exact values in play, so the difference is legible, not just felt.

How it works

Everything hangs off one number. With a 4px base, your scale is 4, 8, 12, 16, 24, 32, 48 — multiples (and near-multiples) of 4. With an 8px base it's 8, 16, 24, 32, 48, which is coarser but enforces even more consistency. Either way, the rule is the same: a spacing value is always a step on the scale, never an arbitrary number.

That rule applies to all three spacing channels — gap (between flex/grid children), padding (inside a container), and margin (between containers). When all three draw from the same scale, the relationships between elements stay proportional no matter how the layout nests.

The cleanest way to enforce this is a spacing token scale: name each step once (--space-1--space-6) and reference the name everywhere. A stray margin: 13px becomes physically harder to write because the value you reach for is a token, not a magic number.

Build it

A spacing scale is just a handful of custom properties referencing one base, then used for every gap, pad, and margin in the card. No magic numbers reach the markup.

CSS
CSS — a 4px-base spacing scale applied to a stacked card
/* One base unit. The scale is multiples of it — nothing else is allowed. */
:root {
  --space-1: 4px; /* 1× */
  --space-2: 8px; /* 2× */
  --space-3: 12px; /* 3× */
  --space-4: 16px; /* 4× */
  --space-5: 24px; /* 6× */
  --space-6: 32px; /* 8× */
}
 
.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-5); /* even rhythm between blocks */
  padding: var(--space-4); /* inner inset */
}
 
.card__thumb {
  height: 7rem;
  border-radius: var(--space-2);
}
 
.card__title {
  margin-bottom: var(--space-1); /* tight: title to body */
}
 
.card__body + .card__body {
  margin-top: var(--space-1); /* same step keeps lines related */
}
 
.card__actions {
  display: flex;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

Make it yours

Use the controls beside the demo above to change base unit and use the consistent scale — each change updates the example live.

Experiment in the playground
  • Audit a screen by listing every spacing value in it — if the list has more than six or seven numbers, or numbers like 13 and 22, you've found the ad-hoc spacing dragging it down.
  • Try the same layout on a 4px base and an 8px base back to back; the 8px version forces fewer, larger steps and usually reads as more confident.
  • Reserve your largest scale steps for separating sections and the smallest for related items (title to its subtitle) — big gaps group, small gaps bind.

Reproduce it with an LLM

Reproduce it with an LLM

You are a design-systems engineer. Define a spacing scale on a 4px base (4, 8, 12, 16, 24, 32, 48, 64) as named CSS custom properties (`--space-1` … `--space-8`). Then lay out a simple stacked card — image, title, body, a row of two buttons — using ONLY those tokens for every margin, padding, and gap, and add a one-line comment on each rule explaining the rhythm choice (why this step and not an arbitrary value). Show how a consistent scale creates vertical rhythm. Return the CSS (tokens + the card) with comments.

Pitfalls & accessibility

  • Don't mix two scales. A 4px scale in one component and an arbitrary set in the next reintroduces exactly the irregularity the base unit was meant to remove — pick one base and enforce it with tokens.

Further reading