Start with the controlling condition
A spacing scale defines the distances available for reuse. Responsive behavior answers a different question: under what condition should one of those distances change? Combining the questions too early produces names such as space-mobile, space-desktop, or space-responsive-lg. Those names expose an implementation guess without explaining the design requirement.
Start with the relationship you need to preserve. The gap between a button icon and label may need to remain stable wherever the button appears. A page shell may need more breathing room after the viewport reaches a recorded threshold. A section gap may grow gradually. A card may need a compact arrangement when its own column becomes narrow, even if the viewport is wide.
These are four different behaviors. Don't implement them by changing every primitive spacing value at one breakpoint.
Do not make the scale responsive by default
If --space-4 changes globally, every consumer inherits the change whether it needs it or not. Keep the primitive value stable and put the conditional decision in the semantic, layout, component, or CSS layer that owns the change.
Separate responsive spacing from nearby concerns
Several changes can make an interface look more or less spacious, but they don't share the same authority. Calling all of them responsive makes implementation and review less precise.
- Viewport or container adaptation responds to available space. This is the responsive behavior covered here.
- Density is a deliberate compact, comfortable, or touch-oriented variant. It can remain compact on a large viewport or comfortable on a small one.
- A visual mode changes presentation under a theme or preference contract. Light and dark modes do not imply different spacing unless the product explicitly requires it.
- Content-driven layout lets wrapping, intrinsic sizing, grid tracks, and document flow respond to content. A long title wrapping to another line does not automatically require another token.
- A local exception is a reviewed departure for a named consumer. Record its reason, owner, and retest or removal trigger instead of disguising it as a reusable token.
Apply two checks. If instances with the same available space need different spacing because of density or product mode, responsiveness does not control the decision. If two instances share a viewport but need different arrangements because their containers differ, the viewport is not the right condition.
Freeze the source contract before writing CSS
Record the consumer, condition, values, owner, exclusions, and expected behavior before implementation. For stepped rules, include the complete ranges. Otherwise, the CSS author has to invent the thresholds.
Source version: design-system 2.4
Spacing decision: page-shell inline gutter
Named consumer: authenticated dashboard shell
Controlling condition: viewport inline size
Owner: application layout
Ranges:
below 48rem: space-4
48rem through below 80rem: space-6
80rem or above: space-8
Fallback before any media query matches: space-4
Expected behavior:
minimum representative width: space-4
intermediate representative width: space-6
maximum representative width: space-8
Exclusions:
- card internal padding
- compact-density tables
- embedded widgets
Approved exceptions: none
Retest triggers:
- source version changes
- threshold contract changes
- shell markup changesThis record is authoritative for the example that follows. It defines both transition edges and the fallback, while the exclusions protect unrelated consumers. A production record should replace the illustrative source version, values, and widths with approved project decisions.
Choose fixed, stepped, fluid, or container-scoped spacing
| Fixed | Stepped | Fluid | Container-scoped | |
|---|---|---|---|---|
| Controlling condition | No responsive condition; the relationship remains stable | A recorded viewport or layout threshold | Continuous change within explicit minimum and maximum bounds | The available size of a containing element |
| Best owner | Primitive, semantic mapping, or component contract | Page or layout contract plus conditional CSS | Layout semantic or local CSS expression | Reusable component contract and its container context |
| Suitable consumers | Control padding, icon gaps, field internals | Page gutters, grid gaps, navigation layouts | Section rhythm, large layout gaps, display spacing | Cards, widgets, panels, and modules used in varied placements |
| Primary risk | Adding needless variants to a stable relationship | Using device labels instead of a real layout threshold | Expecting interpolation to make structural decisions | Responding to the viewport when the component's own space matters |
| Acceptance focus | The relationship stays stable in every required condition | Each exact threshold selects the recorded value | Bounds and intermediate behavior match the expectation | Each named container produces the intended component behavior |
These choices are not levels of sophistication. Fixed spacing is often the right answer. Fluid spacing is not inherently better than stepped spacing, and container queries do not replace viewport rules. A mechanism is useful only when its input matches the requirement.
Start from a complete spacing vocabulary
A design kit can supply stable spacing and layout decisions before a project assigns responsive behavior to named consumers. Browse the published kits, then document which conditions remain owned by your application.
Fixed spacing preserves a local relationship
Use fixed spacing when a relationship should remain recognizable across layouts. Common cases include the gap between an icon and label, padding inside a control, or the distance between a field label and input. The surrounding layout can move, wrap, or change width while the internal relationship stays stable.
:root {
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
}
.action-button {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding-block: var(--space-3);
padding-inline: var(--space-4);
}Don't add a breakpoint merely because the page became narrower. If the button no longer fits, wrapping, label policy, an approved icon-only variant, or the parent layout may own the correction. Shrinking internal spacing can conceal the actual constraint.
Stepped spacing belongs to recorded layout transitions
Use stepped spacing when a layout deliberately changes at explicit thresholds. The source contract above assigns the dashboard shell three ranges: below 48rem, 48rem through below 80rem, and 80rem or above. Each range selects a value from the same stable primitive scale.
:root {
--space-4: 1rem;
--space-6: 1.5rem;
--space-8: 2rem;
--page-gutter: var(--space-4);
}
@media (min-width: 48rem) {
:root {
--page-gutter: var(--space-6);
}
}
@media (min-width: 80rem) {
:root {
--page-gutter: var(--space-8);
}
}
.dashboard-shell {
padding-inline: var(--page-gutter);
}The semantic property --page-gutter owns the selection. The primitives remain stable, so a component consuming --space-4 does not change merely because the viewport crosses 48rem.
Behavior is more useful than a device label
Names such as mobile, tablet, and desktop are weak explanations for a threshold. Record the layout transition and exact condition even if a familiar device label remains in the project's vocabulary.
Fluid spacing interpolates within bounds
Use fluid spacing when continuous growth is the intended behavior. CSS clamp() takes a minimum, a preferred value, and a maximum. It can work for section rhythm or large display spacing where the design does not call for a hard jump.
:root {
--section-gap: clamp(3rem, 2rem + 4vw, 6rem);
}
.marketing-page > section + section {
margin-block-start: var(--section-gap);
}The bounds are design decisions. The preferred expression controls what happens between them. Inspect the minimum-bound region, at least one interpolating condition, and the maximum-bound region.
Interpolation cannot decide when a grid gains a column, navigation changes composition, or a component switches layout. Those are structural decisions. Applying viewport units to every spacing value can also make related elements change at unrelated rates, so keep fluid rules selective and name their consumers.
Inspect the middle
Checking only the minimum and maximum confirms the bounds, not the intended behavior between them. Record an intermediate computed result or visible relationship, but don't treat an unrun example as evidence.
Container-scoped spacing follows component space
Use container-scoped spacing when a reusable component appears in placements with different available widths. A card in a narrow sidebar and the same card in a wide content grid can share a viewport while requiring different arrangements. Its containing element is the relevant condition.
.card-region {
container-type: inline-size;
}
.summary-card {
display: grid;
gap: var(--space-4);
padding: var(--space-4);
}
@container (min-width: 40rem) {
.summary-card {
grid-template-columns: 1fr auto;
gap: var(--space-6);
padding: var(--space-6);
}
}MDN documents that a container size query requires a containment context. That context belongs in the integration contract. Record which element establishes it, which axis or feature is queried, and what the component does when the wider condition does not match.
Reusability alone does not justify a container query. Keep spacing fixed if the internal relationship should remain stable. Use a viewport-owned layout rule if the page changes as one coordinated structure.
Keep the portable artifact boundary honest
A token artifact can carry reusable values, types, groups, descriptions, and aliases. It doesn't automatically own project-specific media queries, container establishment, component markup, cascade order, or acceptance evidence.
The captured DTCG 2025.10 report describes a file format for exchanging design tokens between tools. Its status section identifies it as a preview draft and says not to implement or cite that draft as authoritative. The report can clarify the artifact boundary, but it is not runtime proof or a stable implementation target.
- Source scale: stable reusable distances and their approved meaning.
- Semantic or layout mapping: names such as page gutter or section gap that identify shared intent.
- Component contract: spacing owned by one reusable component, including any container condition.
- Conditional CSS: the media or container rule that selects or computes a value.
- Approved exception: a named deviation with a reason, owner, and retest trigger.
Choose the narrowest owner whose change scope matches the requirement. A global source token is appropriate only when changing it should affect every intended consumer. A component-level decision belongs there only when that component needs independent change authority. Ordinary CSS may be the clearest home for a condition specific to one layout.
Verify representative conditions and exact edges
A valid token artifact and successful build are upstream evidence. They don't prove that the correct rule reached the correct element. Write down the expected result before inspection, then record what you observe without changing the expectation to fit the output.
| Expected behavior | Inspection criteria | Failure condition | Disposition | |
|---|---|---|---|---|
| Minimum representative width: 20rem | The shell uses --space-4 | Inspect computed inline padding and horizontal overflow | Another value resolves, or the shell causes unintended horizontal overflow | Open until observed |
| Lower edge: 47.99rem and 48rem | 47.99rem uses --space-4; 48rem uses --space-6 | Inspect both sides of the recorded 48rem threshold | Either width resolves to the wrong mapping | Open until observed |
| Intermediate representative width: 64rem | The shell uses --space-6; protected component gaps remain stable | Inspect shell padding and the action-button icon gap | The shell uses another value or an excluded consumer changes | Open until observed |
| Upper edge: 79.99rem and 80rem | 79.99rem uses --space-6; 80rem uses --space-8 | Inspect both sides of the recorded 80rem threshold | Either width resolves to the wrong mapping | Open until observed |
| Maximum representative width: 100rem | The shell uses --space-8 and does not continue growing | Inspect computed padding at 100rem and a wider required condition | The gutter changes beyond the recorded maximum mapping | Open until observed |
| Content growth | Long headings and translated labels wrap without replacing the gutter mapping | Use required long content and inspect layout plus computed padding | Content causes an undocumented spacing override or unusable overflow | Open until observed |
| Direction change | Logical inline padding produces the intended start and end gutters in every required writing direction | Inspect each supported direction with the same consumer and conditions | Physical-side assumptions reverse or distort the intended gutters | Open, or not applicable with a recorded reason |
Include the source version, environment, named consumer, exact condition, expected value or relationship, observed result, approved exception, owner, retest trigger, and an accept, revise, or block decision. A note such as "looks good on mobile" can't be reused as precise evidence.
Source version: design-system 2.4
Consumer: authenticated dashboard shell
Environment: [record browser, version, and build]
Condition: viewport inline size = 48rem
Expected: --page-gutter resolves through --space-6
Observed: [fill after inspection]
Protected consumer: action-button icon gap remains --space-2
Exception: none approved
Owner: application layout
Retest trigger: source, threshold, shell, or mapping change
Disposition: accept | revise | blockRoute failures to the first divergent layer
When rendered spacing is wrong, don't begin by editing the nearest declaration. Trace the decision through the delivery chain and stop at the first layer that differs from the approved contract.
- 1
Check the source decision
Confirm that the behavior, values, ranges, version, owner, consumer, fallback, and exclusions are explicit.
- 2
Inspect the emitted artifact
Verify that the expected primitive or alias exists and that transformation did not replace, flatten, or omit it.
- 3
Inspect the project mapping
Confirm that the application maps the source value to the intended semantic or layout property and loads the correct version.
- 4
Inspect the conditional rule
Check the exact media or container condition, cascade order, fallback, and computed value at representative widths and transition edges.
- 5
Inspect the component contract
Confirm that the named consumer uses the shared mapping and that its structure or variant has not introduced a conflicting local value.
- 6
Check approved exceptions
Distinguish a documented exception from an accidental override. An undocumented override is a finding, not an exception.
- 7
Compare the rendered consumer
Record the observation, protected consumers, and disposition. Assign the correction to the owner of the first divergent layer.
This order prevents a local fix from concealing an upstream mismatch. It also protects unrelated consumers from a global token change made to solve one component's problem.
Where Identity Forge stops
Identity Forge kits can supply upstream spacing and layout decisions alongside DESIGN.md, Tailwind, shadcn, and DTCG delivery routes. This gives coding agents and implementation teams a consistent starting vocabulary. It does not prove that a consuming project chose suitable thresholds, established the required containers, mapped every value correctly, adopted shared components, preserved approved exceptions, or passed responsive review.
The consuming project owns its responsive conditions, mappings, component behavior, tests, exceptions, and approval. Treat a kit as the source of the decisions it actually contains, not as evidence about an application it has not inspected.
Take the most reused spacing decision in your project and classify it as fixed, stepped, fluid, or container-scoped before adding another conditional token. If you can't name its controlling condition, consumer, and owner, the token is not ready to create.
Sources
- Spacing - Carbon Design System: Carbon documents a spacing scale, distinguishes component spacing from layout spacing, and describes additional layout mechanisms such as stacks, gutters, and custom gaps.
- Design Tokens - Mozilla Protocol: Mozilla Protocol publishes separate spacing and layout token families along with content-width, screen-width, and media-query values.
- Design Tokens beyond colors, typography, and spacing: The Bumble Tech article discusses extending token responsibility from global foundations into component-level decisions.
- CSS container queries - MDN Web Docs: MDN documents container size queries and the need to establish a containment context before querying a container.
- Using container size and style queries - MDN Web Docs: MDN distinguishes media queries based on viewport or device conditions from container queries based on a containing element.
- clamp() CSS function - MDN Web Docs: MDN defines clamp() as a CSS function that keeps a preferred value between specified minimum and maximum bounds.
- Design Tokens Format Module 2025.10: The captured DTCG document describes a token exchange format and identifies itself as a preview draft that must not be treated as an authoritative implementation target.
- Identity Forge: Identity Forge presents design kits containing tokens, typography, spacing and layout guidance, DESIGN.md instructions, and delivery routes for coding agents and web projects.