Spacing
The 4-point grid, semantic padding and gap tokens, the device-fluid layout tier, and the primitive scale.
Spacing tokens control padding, margins, and gaps. Each token answers to exactly one axis:
| Axis | Tokens | Varies with |
|---|---|---|
| Density | --padding-*, --gap-* | [data-mode-spacing] on :root — one value at every viewport |
| Device | --bds-page-inset, --bds-section-padding-block (the layout tier) | Viewport width — fluid from mobile to desktop, never by density |
No token takes both, so density modes and device modes never multiply (ADR-042).
Spacing values are multiples of 4px, with two named exceptions. npm run lint-tokens:grid reports off-grid values as warnings — it is a review aid, not a merge gate. What does block is spacing-mode-track (part of npm run validate): every [data-mode-spacing] track must stay a strictly increasing seven-rung scale with no rung at 0px, and any override it declares must be on-grid.
The two exceptions. Micro values — 0, 1px, 2px — sit below the grid's resolution. Half-steps — --space-150 / -250 / -350 / -450 (6 / 10 / 14 / 18px) — are one deliberate 2px-offset rung between each pair of 4pt rungs up to --space-500, for optical adjustments finer than a full step. Above 500 the ramp stops half-stepping. Both are Figma-backed and exempt from the grid check; a new off-grid value is not.
Semantic padding tokens
Purpose-bound spacing used in components. These values change between Base and Spacious modes.
Padding
| Preview | Token | CSS Variable | Maps to |
|---|---|---|---|
| padding-none | --padding-none | var(--bds-space-0) | |
| padding-tiny | --padding-tiny | var(--bds-space-200) | |
| padding-xs | --padding-xs | var(--bds-space-250) | |
| padding-sm | --padding-sm | var(--bds-space-300) | |
| padding-md | --padding-md | var(--bds-space-400) | |
| padding-lg | --padding-lg | var(--bds-space-600) | |
| padding-xl | --padding-xl | var(--bds-space-800) | |
| padding-huge | --padding-huge | var(--bds-space-1200) |
Semantic gap tokens
Gap tokens for flex and grid layouts. Typically smaller than the equivalent padding tokens.
Gap
| Preview | Token | CSS Variable | Maps to |
|---|---|---|---|
| gap-none | --gap-none | var(--bds-space-0) | |
| gap-tiny | --gap-tiny | var(--bds-space-50) | |
| gap-xs | --gap-xs | var(--bds-space-100) | |
| gap-sm | --gap-sm | var(--bds-space-150) | |
| gap-md | --gap-md | var(--bds-space-200) | |
| gap-lg | --gap-lg | var(--bds-space-400) | |
| gap-xl | --gap-xl | var(--bds-space-600) | |
| gap-huge | --gap-huge | var(--bds-space-800) |
Spacing modes
Three named modes plus default modulate --padding-* and --gap-*:
- Default (no attribute) — values from
figma-tokens.cssbase. Used by product apps. compact— tighter spacing for dense interfaces.comfortable— moderate increase from default.spacious— large increase, typical for marketing sites and.body-classed surfaces.
Mode values auto-generate at tokens/modes-spacing.css — never hand-edit. Re-run npm run build:sd-figma after a Figma mode update.
Layout tier
Two tokens set the page frame, and they are the only spacing tokens that change with the viewport. They scale smoothly between three device endpoints and stay flat above desktop.
| Token | Fills | Mobile 320 | Tablet 768 | Desktop 1440+ |
|---|---|---|---|---|
--bds-page-inset | padding-inline — viewport edge ↔ content band | 16px (--bds-space-400) | 32px (--bds-space-800) | 96px (--bds-space-2100) |
--bds-section-padding-block | padding-block — a section's top and bottom band | 64px (--bds-space-1600) | 80px (--bds-space-1800) | 104px (--bds-space-2200) |
.my-section {
padding-block: var(--bds-section-padding-block);
}
.my-section__container {
max-width: var(--bds-content-width-xl);
margin-inline: auto;
padding-inline: var(--bds-page-inset);
}In TS, import pageInset and sectionPaddingBlock from @bds-tokens rather than writing the var() string inline.
Where the values come from. The Figma Foundations library has a layout collection with three modes — desktop, tablet, mobile. Each variable aliases a spacing primitive. Switch a frame's mode to mock a smaller device.
How it becomes fluid. Figma variables hold static numbers, so the build turns the three modes into one value: two clamp() segments added together, one from mobile to tablet and one from tablet to desktop. The widths are read from --breakpoint-mobile, --breakpoint-tablet and --breakpoint-wider. Output lands in tokens/layout-fluid.css — never hand-edit. Re-run npm run build:modes after a Figma change.
--bds-page-inset: calc(clamp(1rem, 0.2857rem + 3.5714vw, 2rem) + clamp(0rem, -4.5714rem + 9.5238vw, 4rem));Never re-declare a layout-tier value in a site. No site-level clamp(), no @media override of --page-inset. The nav and every section read the same token, so they cannot drift apart. A component that needs a different step at a breakpoint picks another fixed token inside an @media on a --breakpoint-* rung — the component tokens themselves never change with viewport width.
Accessibility. Bounds are in rem, so the floors grow with the user's font size. At 320px the inset floors at 16px per side, leaving a 288px content box for WCAG 1.4.10 Reflow.
Space scale
The raw spacing scale from 0 to 176px. Semantic tokens reference these steps.
--space-00px--space-251px--space-502px--space-1004px--space-1506px--space-2008px--space-25010px--space-30012px--space-35014px--space-40016px--space-45018px--space-50020px--space-60024px--space-70028px--space-80032px--space-90036px--space-100040px--space-110044px--space-120048px--space-130052px--space-140056px--space-150060px--space-160064px--space-170072px--space-180080px--space-190084px--space-200088px--space-210096px--space-2200104px--space-2300112px--space-2400128px--space-2500136px--space-2600144px--space-2700152px--space-2800160px--space-2900168px--space-3000176pxRelated
- Content Rhythm — the standard these tokens serve: which gap goes between which pair of elements, and where each step is set. This page is the catalog; that page is the rule.
- Page Grid — the horizontal axis: the width-container recipe and
--page-inset - Screen breakpoints — the
--breakpoint-*rungs the layout tier's endpoints sit on - Cascade rules — how layers interact
- Color tokens — semantic surface tokens that pair with these spacings
- Typography tokens — type scale for content within these spaces