Semantic Spacing and Layout Rhythm Tokens (CEM × M3)

Status: Canonical (D1 v1.0)

Last updated: December 19, 2025

Audience: Design Systems, Product Design, Front-End Engineering

Taxonomy placement: D1. Space & Rhythm (part of the 7-dimensional CEM token framework)

Companion specs:


Table of Contents

  1. Scope
  2. CEM alignment principles applied to spacing
  3. Token model
  4. Relation to Dimensional Tokens
  5. Reference spacing scale (semantic)
  6. Consumer-semantic spacing taxonomy
  7. Layout rhythm tokens (compositional semantics)
  8. Spacing modes knob (dense / normal / sparse)
  9. Mapping notes: M3 ↔ CEM
  10. Quick adoption checklist

Appendices


1. Scope

This document defines a consumer-semantic spacing and layout rhythm token set that:

This document is D1 (Space & Rhythm). It intentionally does not define interactive minimums; it consumes D2 coupling minimums as hard constraints.


2. CEM alignment principles applied to spacing

2.1 Semantic intent first

Developers should apply tokens like:

…and not value-centric names like space-16 in component code.

2.2 Bounded variation

A small set of distinct, repeatable space steps should cover most UI. Extended values exist but are intentionally “rare”.

2.3 Accessibility and operability by construction

Spacing must preserve:


3. Token model

We use three layers:

  1. Reference scale tokens (M3-aligned numeric steps; safe to map to dp/px)
  2. System/semantic tokens (consumer-intent endpoints; what teams apply)
  3. Component mapping (component-specific tokens map to semantic tokens; typically owned in component adapters)

4. Relation to Dimensional Tokens

4.1 Dimensional Tokens: where spacing lives

In CEM, spacing/rhythm is not “just layout.” It is a primary subset of Dimensional Tokens (the physical layer: size, distance, bend, stroke, depth).

Use this legend-level dimensional taxonomy to keep token categories coherent:

4.2 Governance rules (cross-category contracts)

These rules prevent spacing changes from degrading operability, accessibility, or visual hierarchy:

  1. Spacing modes are a D1 adjustment; never a D2 coupling regression
  1. Normative layout contract for interactive adjacency

When spacing occurs between two interactive affordances, layout must respect D2 guard:

/* If the gap separates adjacent interactive affordances: */
.cem-gap-interactive {
    gap: max(var(--cem-gap-related), var(--cem-coupling-guard-min));
}
  1. When D1 can’t grow, D5 may need to compensate
  1. Elevated/prominent surfaces “earn” breathing room
  1. Bend and inset should harmonize (D1 × D3)
  1. Reading cadence is jointly governed by typography + spacing

5. Reference spacing scale (semantic)

The spacing scale uses semantic size names rather than pixel values, making intent clear while preserving M3 rhythm (4dp increments).

5.1 Primary dimension scale (semantic.css)

Eight steps covering common UI needs:

cem-dim-scale
Token Value Description tier
--cem-dim-xx-small 0.25rem 4px — micro gaps, icon padding required
--cem-dim-x-small 0.5rem 8px — related item gaps, control insets required
--cem-dim-small 0.75rem 12px — group gaps, inline rhythm required
--cem-dim-medium 1rem 16px — block gaps, container insets required
--cem-dim-large 1.5rem 24px — section gaps, surface insets required
--cem-dim-x-large 2rem 32px — page gaps, wide gutters required
--cem-dim-xx-large 4rem 64px — extended layout, hero spacing required
--cem-dim-xxx-large 8rem 128px — maximum breathing room required

Cross-reference: These tokens are consumed by D3 Shape (cem-shape) for bend values:

5.2 Mapping to M3 rhythm

Semantic token Value M3 dp equivalent Typical use
--cem-dim-xx-small 0.25rem 4dp Micro gaps, tight padding
--cem-dim-x-small 0.5rem 8dp Related items, control insets
--cem-dim-small 0.75rem 12dp Group gaps, inline spacing
--cem-dim-medium 1rem 16dp Block gaps, container insets
--cem-dim-large 1.5rem 24dp Section gaps, surface padding
--cem-dim-x-large 2rem 32dp Page gaps, wide gutters
--cem-dim-xx-large 4rem 64dp Extended layout spacing
--cem-dim-xxx-large 8rem 128dp Maximum layout spacing

6. Consumer-semantic spacing taxonomy

The taxonomy is organized by what the space means to the user.

6.1 Relationship gaps (between items)

Use when arranging siblings.

cem-dim-gaps
Token Value Description tier
--cem-gap-related var(--cem-dim-x-small) Siblings in the same unit (8px) recommended
--cem-gap-group var(--cem-dim-small) Items in the same group, distinct (12px) recommended
--cem-gap-block var(--cem-dim-medium) Between groups/blocks inside one surface (16px) recommended
--cem-gap-section var(--cem-dim-large) Between major sections (24px) recommended
--cem-gap-page var(--cem-dim-x-large) Between page-level regions (32px) recommended

Guideline: if users perceive two things as “one unit,” use gap-related. If they perceive “these are separate things,” move up to gap-group or gap-block.

Important: for interactive adjacency, apply the D2 guard contract (gap = max(D1 gap, D2 guard)).

6.2 Insets (inside a surface)

Use when padding content within a container.

cem-dim-insets
Token Value Description tier
--cem-inset-control var(--cem-dim-x-small) Smallest safe inset for tight controls (8px) recommended
--cem-inset-container var(--cem-dim-medium) Default inset for common containers (16px) recommended
--cem-inset-surface var(--cem-dim-large) Comfortable inset for reading surfaces and prominent cards (24px) recommended

Cross-reference: When combining insets with bend (D3), ensure inset is large enough to prevent content crowding in rounded corners. See cem-shape §8.5 for guidance.

6.3 Coupling and interaction safety (D2 cross-reference)

These tokens are defined and governed in D2 (cem-coupling). They are listed here as a * normative constraint* because they bound how far D1 spacing modes can compress interactive adjacency. Do not set or tune these in D1; treat them as sourced from the D2 theme.

:root {
    /* Minimum distancing between adjacent operable zones (prevents interference). */
    --cem-coupling-guard-min: 0.5rem; /* nominally 8px */

    /* Minimum operable zone (layout-level). Keep invariant across modes. */
    --cem-coupling-zone-min: 3rem; /* nominally 48px @ 16px root */

    /* Invisible expansion beyond visuals (halo). */
    --cem-coupling-halo: 0.25rem; /* nominally 4px */

    /* Legacy aliases (deprecated): keep only while migrating older code */
    --cem-touch-separation-min: var(--cem-coupling-guard-min);
    --cem-touch-target-min: var(--cem-coupling-zone-min);
}

Interpretation (summary):

6.4 Reading rhythm (vertical cadence for prose)

This is distinct from UI rhythm.

cem-dim-rhythm-reading
Token Value Description tier
--cem-rhythm-reading-paragraph 0.75em Default paragraph spacing for prose recommended
--cem-rhythm-reading-section var(--cem-dim-large) Space between reading sections within one surface (24px) recommended

Cross-reference: Reading rhythm must be validated against typography tokens. See cem-voice-fonts-typography.

6.5 Data/scan rhythm (dense but legible)

Optimized for scan/compare flows (tables, metrics).

cem-dim-rhythm-data
Token Value Description tier
--cem-rhythm-data-row var(--cem-dim-x-small) Table-like, scan-first row padding (8px) recommended
--cem-rhythm-data-group var(--cem-dim-medium) Scan grouping — subtotals, row groups, metric clusters (16px) recommended

7. Layout rhythm tokens (compositional semantics)

These describe layout structures without baking in specific components.

7.1 Stack rhythm (vertical composition)

Default vertical stack gap for general UI stacks. Optional tight/loose variants for systems that need explicit range.

7.2 Cluster rhythm (horizontal groups)

Default cluster gap for inline groups (icons + text, toolbars, button clusters). The legacy --cem-layout-inline-* aliases are deprecated — use --cem-gap-* instead.

7.3 Page gutters (responsive breathing room)

These are responsive and should be treated as semantics, not fixed numbers.

7.4 Layout token table

cem-dim-layout
Token Value Description tier
--cem-layout-stack-gap var(--cem-gap-block) Default vertical stack gap for general UI stacks required
--cem-layout-cluster-gap var(--cem-gap-related) Default cluster gap for inline groups required
--cem-layout-gutter var(--cem-dim-medium) Default content gutter (16px) required
--cem-layout-gutter-wide var(--cem-dim-x-large) Wide-screen gutter (32px) recommended
--cem-layout-gutter-max var(--cem-dim-xx-large) Maximum gutter (64px) recommended
--cem-layout-stack-tight var(--cem-gap-related) Tight stack variant — rare, use only when explicitly tighter than default optional
--cem-layout-stack-loose var(--cem-gap-section) Loose stack variant — rare, use only when explicitly looser than default optional
--cem-layout-inline-tight var(--cem-dim-x-small) Deprecated — use --cem-gap-related deprecated
--cem-layout-inline var(--cem-dim-small) Deprecated — use --cem-gap-group deprecated
--cem-layout-inline-loose var(--cem-dim-medium) Deprecated — use --cem-gap-block deprecated

8. Spacing modes knob (dense / normal / sparse)

Material often frames this as “density.” In CEM, treat this explicitly as a D1 spacing mode that shifts Space & Rhythm while preserving D2 coupling invariants.

:root {
    /* dense | normal | sparse */
    --cem-layout-spacing: normal;
}

8.1 Adjustment policy

Mode intent summary:

D1 spacing mode Primary goal What changes What must not change
dense Increase information density Step down gaps/insets/gutters ~1 step where safe D2 coupling invariants (zone/guard), and any gap that separates interactive affordances must still satisfy gap = max(D1 gap, D2 guard)
normal Baseline Use canonical endpoints as defined Same invariants
sparse Increase calm/readability Step up gaps/insets/gutters ~1 step Same invariants

Hard constraints (never override):

normal mode uses the baseline values defined in §6–7. dense steps gaps down ~1 scale step; sparse steps them up ~1 step. Tokens not in this table are unaffected by spacing mode.

cem-dim-spacing-overrides
Token dense sparse
--cem-gap-related var(--cem-dim-x-small) var(--cem-dim-small)
--cem-gap-group var(--cem-dim-x-small) var(--cem-dim-medium)
--cem-gap-block var(--cem-dim-small) var(--cem-dim-large)
--cem-gap-section var(--cem-dim-medium) var(--cem-dim-x-large)
--cem-gap-page var(--cem-dim-large) var(--cem-dim-xx-large)
--cem-inset-control var(--cem-dim-x-small) var(--cem-dim-small)
--cem-inset-container var(--cem-dim-small) var(--cem-dim-large)
--cem-inset-surface var(--cem-dim-medium) var(--cem-dim-x-large)
--cem-layout-gutter var(--cem-dim-small) var(--cem-dim-large)
--cem-layout-gutter-wide var(--cem-dim-large) var(--cem-dim-xx-large)
--cem-layout-gutter-max var(--cem-dim-x-large) var(--cem-dim-xxx-large)
--cem-rhythm-reading-paragraph 0.6em 1em
--cem-rhythm-reading-section var(--cem-dim-medium) var(--cem-dim-x-large)
--cem-rhythm-data-row var(--cem-dim-xx-small) var(--cem-dim-small)
--cem-rhythm-data-group var(--cem-dim-small) var(--cem-dim-large)

8.3 Notes on component mapping

8.4 Layout mapping checklist (how to apply)

Use these patterns so teams can implement screens without inventing spacing semantics.

Stacks (vertical composition)

Clusters (horizontal composition)

Cards / panels / surfaces

Sections and page regions

Gutters (responsive framing)

Reading and data cadence


9. Mapping notes: M3 ↔ CEM

9.1 Where this matches Material 3

9.2 Where this differs (intentionally)


10. Quick adoption checklist

  1. Use the dimension scale (--cem-dim-*) as the foundation.
  2. Map semantic endpoints (gap-*, inset-*, rhythm-*) to dimension tokens.
  3. Treat D2 coupling (zone/guard/halo) as hard constraints for interactive adjacency — see cem-coupling.
  4. Update component tokens to use semantic endpoints.
  5. Add optional data-cem-spacing="dense|normal|sparse" only if product needs spacing modes.
  6. Validate on representative surfaces:
  7. Validate bend-inset harmony on rounded surfaces — see cem-shape §8.5.

Appendix A. D2 Coupling Mode Matrix (excerpt)

This excerpt is provided for convenience when working in D1. The canonical safety definitions and governance live in D2. Coupling & Compactness (cem-coupling); visual geometry values live in D2c. Controls (cem-controls).

Coupling mode Product intent D2c Controls visual geometry trend D2 halo (--cem-coupling-halo) trend Typical surfaces
forgiving Minimize mis-coupling for imprecise input Larger controls/rows; more internal padding Smaller (visuals already meet zone) mobile-first, kiosks, accessibility-first, gaze/dwell
balanced Default across modalities Baseline control heights/rows Baseline mixed pointer + touch, general app UI
compact Increase information density without breaking operability Smaller visuals; reduced chrome Larger (use halo to preserve zone) data grids, admin tools, scan-heavy panels

Normative invariants (do not override in D1):


Appendix B. Governance and versioning

This D1 spec is a contract. Changes must be intentional, reviewable, and versioned.

B.1 What counts as breaking

Treat as major (breaking) if you:

B.2 What is non-breaking

Treat as minor/patch if you:

B.3 Versioning guidance

B.4 Canonical cross-spec invariants

D1 is subordinate to D2 for operability. The following must hold in every release:


11. Acceptance criteria

Interactive-adjacency contract (non-normative for generator): any consumer using D1 gaps between interactive affordances must resolve the effective gap as:

gap:

max
(
var
(
--cem-gap-related

)
,
var
(
--cem-coupling-guard-min

)
)
;

The generator does not enforce this — it is component-author responsibility, documented in the manifest notes above.

Reading-rhythm validation is deferred to D6 cross-check (Phase 12 in the implementation plan). D1 cannot validate rhythm in isolation.

12. Token manifest index

Token tier is encoded in the tier column of each source table. The manifest validator derives expected token names from these tables using the same XPath pattern as cem-dimension.html.

Source table h6 id Tokens covered Validator derivation
cem-dim-scale --cem-dim-* (8 tokens) one token per row
cem-dim-gaps --cem-gap-* (5 tokens) one token per row
cem-dim-insets --cem-inset-* (3 tokens) one token per row
cem-dim-rhythm-reading --cem-rhythm-reading-* (2 tokens) one token per row
cem-dim-rhythm-data --cem-rhythm-data-* (2 tokens) one token per row
cem-dim-layout --cem-layout-* (10 tokens; deprecated tier omitted from default output) one token per row

Spacing mode overrides (cem-dim-spacing-overrides) produce no new token names — they override existing tokens within :root[data-cem-spacing="dense"] and :root[data-cem-spacing="sparse"] selectors.


References

Local CEM documentation