Semantic Spacing and Layout Rhythm Tokens (CEM × M3)

Status: Canonical (D1 v1.0)

Last updated: August 10, 2026

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

The explicit density policies in D2 §6.0 are independently opted in and have their own target/guard values. Compact is gated to precise input; explicitly authored super-compact is content-sized on every input modality. Neither changes the canonical spacing mode values or the normal/default coupling contract.

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
TokenValueDescriptiontier
--cem-dim-xx-small0.25rem4px — micro gaps, icon paddingrequired
--cem-dim-x-small0.5rem8px — related item gaps, control insetsrequired
--cem-dim-small0.75rem12px — group gaps, inline rhythmrequired
--cem-dim-medium1rem16px — block gaps, container insetsrequired
--cem-dim-large1.5rem24px — section gaps, surface insetsrequired
--cem-dim-x-large2rem32px — page gaps, wide guttersrequired
--cem-dim-xx-large4rem64px — extended layout, hero spacingrequired
--cem-dim-xxx-large8rem128px — maximum breathing roomrequired

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

5.2 Mapping to M3 rhythm

Semantic tokenValueM3 dp equivalentTypical use
--cem-dim-xx-small0.25rem4dpMicro gaps, tight padding
--cem-dim-x-small0.5rem8dpRelated items, control insets
--cem-dim-small0.75rem12dpGroup gaps, inline spacing
--cem-dim-medium1rem16dpBlock gaps, container insets
--cem-dim-large1.5rem24dpSection gaps, surface padding
--cem-dim-x-large2rem32dpPage gaps, wide gutters
--cem-dim-xx-large4rem64dpExtended layout spacing
--cem-dim-xxx-large8rem128dpMaximum 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
TokenValueDescriptiontier
--cem-gap-relatedvar(--cem-dim-x-small)Siblings in the same unit (8px)recommended
--cem-gap-groupvar(--cem-dim-small)Items in the same group, distinct (12px)recommended
--cem-gap-blockvar(--cem-dim-medium)Between groups/blocks inside one surface (16px)recommended
--cem-gap-sectionvar(--cem-dim-large)Between major sections (24px)recommended
--cem-gap-pagevar(--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
TokenValueDescriptiontier
--cem-inset-controlvar(--cem-dim-x-small)Smallest safe inset for tight controls (8px)recommended
--cem-inset-containervar(--cem-dim-medium)Default inset for common containers (16px)recommended
--cem-inset-surfacevar(--cem-dim-large)Comfortable inset for reading surfaces and prominent cards (24px)recommended
--cem-menu-insetmax(var(--cem-inset-control), var(--cem-coupling-guard-min))Menu surface clearance around outer item indicators; retained in compressed densityrequired
--cem-menu-item-gapmax(var(--cem-gap-related), calc(2 * var(--cem-coupling-guard-min)))Menu item separation reserves room for simultaneous selected and focused indicatorsrequired

Menu inset and item-gap endpoints express preferred spacing independently of control padding. Super-compact may reduce those preferences to zero/related spacing, while the menu layout still reserves the actual outward indicator extent from D0 stripe thickness and D5 focus width/offset. The current three-stripe ring requires at least 3 × --cem-zebra-strip-size at surface edges and twice that between adjacent items. Focus outlines can require a larger floor. Compute this bound where the menu lays out its children so inherited stripe and stroke overrides remain effective below an ancestor density boundary. Density never removes this paint clearance or increases generic button padding.

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

6.3 Coupling and interaction safety (D2 cross-reference)

These tokens are defined and governed in D2 (cem-coupling.md). 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
TokenValueDescriptiontier
--cem-rhythm-reading-paragraph0.75emDefault paragraph spacing for proserecommended
--cem-rhythm-reading-sectionvar(--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.md.

6.5 Data/scan rhythm (dense but legible)

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

cem-dim-rhythm-data
TokenValueDescriptiontier
--cem-rhythm-data-rowvar(--cem-dim-x-small)Table-like, scan-first row padding (8px)recommended
--cem-rhythm-data-groupvar(--cem-dim-medium)Scan grouping — subtotals, row groups, metric clusters (16px)recommended
--cem-data-row-padding-blockvar(--cem-control-padding-y)Structured row block inset; shared by trees and tabular viewsrequired
--cem-data-row-padding-inlinevar(--cem-control-padding-x)Structured row inline inset; hierarchy indentation is separaterequired
--cem-data-row-gapvar(--cem-gap-related)Vertical spacing between structured rows and groupsrequired
--cem-data-tree-padding-factor0.5Tree row padding multiplier applied to inherited control padding; sparse uses full paddingrequired
--cem-data-tree-indentvar(--cem-control-padding-x)Hierarchy indentation independent of row paddingrequired
--cem-data-tree-padding-inline0pxOuter tree inset, independent of per-level indentationrequired
--cem-data-tree-column-gapvar(--cem-gap-related)Horizontal separation of tree disclosure, icon and labelrequired

6.6 Inherited density profiles

data-cem-density="compact" is an inherited desktop chrome recipe. Use data-cem-density="super-compact" on a page/container alongside data-theme for content-sized application chrome and structured trees/tabular data. Controls have zero padding; structured rows follow adjacent lines of one paragraph, with no extra padding or vertical gap. Structured rows retain a 1lh minimum; generic buttons have no imposed height minimum, so content, wrapped labels and user text scaling can grow naturally. Icons remain 1em; the profile never scales the font to manufacture density. Tree geometry distinguishes its 0.25em outer inline inset, 0.25em horizontal column gaps and 1.4em increment per nesting level. These follow the row font; they do not introduce row padding or vertical spacing between paragraph lines.

Compact requires a fine primary pointer with hover and no coarse pointer at all. Super-compact is an explicit geometry choice on every input modality; coarse, unknown and hybrid input do not reinstate its padding or insets. These profiles are separate from existing spacing/coupling modes, which retain their previous values. D2 owns the requested target policy; D2c owns row/control geometry and D5 keeps structured-row focus inside its line. Components consume these tokens without per-component density recipes.

data-cem-density="normal" establishes a nested baseline boundary by reading the original canonical values for the density table's endpoints. It restores insets, gutters and data-row geometry without redefining typography or unrelated spacing tokens. Omission keeps the ancestor's density. data-cem-spacing remains an independent spacing choice; use data-cem-density="normal" together with data-cem-spacing="sparse" to show a sparse sample inside a condensed page.

cem-dim-density-overrides
Tokencompactsuper-compact
--cem-gap-related0.25rem0.25rem
--cem-gap-group0.5rem0.5rem
--cem-gap-block0.5rem0.5rem
--cem-gap-section0.75rem0.75rem
--cem-inset-control0.25rem0px
--cem-menu-insetmax(var(--cem-inset-control), var(--cem-coupling-guard-min))0px
--cem-menu-item-gapmax(var(--cem-gap-related), calc(2 * var(--cem-coupling-guard-min)))var(--cem-gap-related)
--cem-inset-container0.5rem0px
--cem-inset-surface0.75rem0px
--cem-layout-gutter0.5rem0px
--cem-data-row-padding-blockvar(--cem-control-padding-y)0px
--cem-data-row-padding-inlinevar(--cem-control-padding-x)0px
--cem-data-row-gapvar(--cem-gap-related)0px
--cem-data-tree-indent1.4em1.4em
--cem-data-tree-padding-inline0.25em0.25em
--cem-data-tree-column-gap0.25em0.25em

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.

Intrinsic grid sizing

--cem-layout-grid-min owns the minimum usable track width for intrinsic, container-driven grids. Its default 14rem adopts the canonical D1y intrinsic Grid example. Containers may override this endpoint for their content; components consume it without local defaults and cap the minimum to available inline space. This layout threshold is independent of D6's maximum reading-line measure. Reading content retains its own maximum-measure requirement, and explicit column counts remain an authored layout choice.

7.4 Layout token table

cem-dim-layout
TokenValueDescriptiontier
--cem-layout-stack-gapvar(--cem-gap-block)Default vertical stack gap for general UI stacksrequired
--cem-layout-grid-min14remMinimum usable track width for intrinsic grids; cap to available container widthrequired
--cem-layout-cluster-gapvar(--cem-gap-related)Default cluster gap for inline groupsrequired
--cem-layout-guttervar(--cem-dim-medium)Default content gutter (16px)required
--cem-layout-gutter-widevar(--cem-dim-x-large)Wide-screen gutter (32px)recommended
--cem-layout-gutter-maxvar(--cem-dim-xx-large)Maximum gutter (64px)recommended
--cem-layout-stack-tightvar(--cem-gap-related)Tight stack variant — rare, use only when explicitly tighter than defaultoptional
--cem-layout-stack-loosevar(--cem-gap-section)Loose stack variant — rare, use only when explicitly looser than defaultoptional
--cem-layout-inline-tightvar(--cem-dim-x-small)Deprecated — use --cem-gap-relateddeprecated
--cem-layout-inlinevar(--cem-dim-small)Deprecated — use --cem-gap-groupdeprecated
--cem-layout-inline-loosevar(--cem-dim-medium)Deprecated — use --cem-gap-blockdeprecated

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 modePrimary goalWhat changesWhat must not change
denseIncrease information densityStep down gaps/insets/gutters ~1 step where safeD2 coupling invariants (zone/guard), and any gap that separates interactive affordances must still satisfy gap = max(D1 gap, D2 guard)
normalBaselineUse canonical endpoints as definedSame invariants
sparseIncrease calm/readabilityStep up gaps/insets/gutters ~1 stepSame invariants

data-cem-spacing="dense|normal|sparse" may be placed on a container or component host; the canonical endpoints are inherited by its descendants. An explicit normal boundary restores the original values of the spacing table's endpoints even under a dense/sparse ancestor. Omitting the attribute inherits its parent. Spacing changes gaps and insets; condensed control/tree row heights are selected separately with data-cem-density="super-compact". Normal spacing alone does not reset density or its operable minimums. On one boundary, an explicit compact density selects its complete geometry after spacing; nested boundaries may choose a different spacing or density for their descendants.

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
Tokendensesparse
--cem-data-tree-padding-factor0.51
--cem-gap-relatedvar(--cem-dim-x-small)var(--cem-dim-small)
--cem-gap-groupvar(--cem-dim-x-small)var(--cem-dim-medium)
--cem-gap-blockvar(--cem-dim-small)var(--cem-dim-large)
--cem-gap-sectionvar(--cem-dim-medium)var(--cem-dim-x-large)
--cem-gap-pagevar(--cem-dim-large)var(--cem-dim-xx-large)
--cem-inset-controlvar(--cem-dim-x-small)var(--cem-dim-small)
--cem-inset-containervar(--cem-dim-small)var(--cem-dim-large)
--cem-inset-surfacevar(--cem-dim-medium)var(--cem-dim-x-large)
--cem-layout-guttervar(--cem-dim-small)var(--cem-dim-large)
--cem-layout-gutter-widevar(--cem-dim-large)var(--cem-dim-xx-large)
--cem-layout-gutter-maxvar(--cem-dim-x-large)var(--cem-dim-xxx-large)
--cem-rhythm-reading-paragraph0.6em1em
--cem-rhythm-reading-sectionvar(--cem-dim-medium)var(--cem-dim-x-large)
--cem-rhythm-data-rowvar(--cem-dim-xx-small)var(--cem-dim-small)
--cem-rhythm-data-groupvar(--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.md.
  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.md §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.md); visual geometry values live in D2c. Controls (cem-controls.md).

Coupling modeProduct intentD2c Controls visual geometry trendD2 halo (--cem-coupling-halo) trendTypical surfaces
forgivingMinimize mis-coupling for imprecise inputLarger controls/rows; more internal paddingSmaller (visuals already meet zone)mobile-first, kiosks, accessibility-first, gaze/dwell
balancedDefault across modalitiesBaseline control heights/rowsBaselinemixed pointer + touch, general app UI
compactIncrease information density without breaking operabilitySmaller visuals; reduced chromeLarger (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 idTokens coveredValidator 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-* and menu surface inset/item-gap endpointsone token per row
cem-dim-rhythm-reading--cem-rhythm-reading-* (2 tokens)one token per row
cem-dim-rhythm-data--cem-rhythm-data-* and structured --cem-data-row-* insets/gapsone token per row
cem-dim-density-overridesPrecise-input inherited desktop profiles; no new tokensoverrides only
cem-dim-layout--cem-layout-* (11 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

Decision: optional component dimensions and compact hit areas

Control size belongs to D2c Controls, while D2 Coupling owns operability and D1 owns layout spacing. Do not map control size="large" to the D1 spacing token --cem-dim-large.

The 3rem target is CEM policy, not a claim of automatic ADA conformance. At a 16px root it is 48 CSS pixels; consumers must assess actual computed dimensions.

Size roles and composition

Size expresses available space and prominence. Content type suggests useful examples, but does not select size automatically. Keep medium as the API spelling for an ordinary standalone action; normal is not an additional value.

ProfileTypical useMinimum visible height
OmittedContent-sized or container-sized action; inherits theme geometryInherited
smallInline action, table-row control, compact toolbar icon2.5rem
mediumStandalone text action, text with icon, ordinary icon action3rem
largeProminent confirmation or large playback control4rem
x-largeOne choice represented by an image and title6rem
xx-largeFeatured choice or CMS hero composition with one action8rem

An icon-only action can use any profile. Glyph size, content layout, intent, coupling and control height remain independent. The xx-large baseline continues the 4/6/8rem progression for large controls; it is a starting minimum, not a fixed hero height or a reuse of the D1 --cem-dim-xx-large spacing token. Images, wrapping text and responsive container layout determine the final size. Only requested geometry below the coupling minimum adds the transparent hit border. Medium and larger default profiles add none, including tiles and heroes. An overridden profile below that minimum still receives the safety inset.

Compose image/title content through the default slot using noninteractive phrasing content, such as spans, images and strong text. The action permits label wrapping; the author owns stacked or responsive layouts inside the projected content. Size never silently changes row/column layout, font scale or image size. Keep content readable under zoom and narrow containers rather than clipping it to a preset height. A small profile stretched by layout retains its reserved compact inset; this policy follows requested geometry, not DOM measurement.

Semantics follow behavior at every size: a command uses a native button and a destination uses a native link. The current cem-action owns a native button; the image and hero playground samples therefore choose content, not navigate. Adding native-link support is a separate component contract change. A card with an interactive preview or several actions keeps those controls separate; do not nest them inside one action. The legacy material demo-list-card follows this composition: the preview is a sibling of a title/description link with a 6rem minimum height.

This decision draws on Angular Material buttons, Material 3 Expressive button sizes, icon button sizes, and Angular Material card composition. Material offers size choices for both text and icon buttons; CEM retains its own theme scale and coupling minimum.