Color tokens resolve quickly in most design system conversations. The designer says "primary button is mint green," someone opens the token file, adds --color-primary: #3DFFA3, and the discussion moves on. Typography and spacing tokens take three times as long and generate twice as much disagreement. The root cause is that designers and engineers are not solving the same problem when they think about text and space.
Designers think in visual rhythm. A type scale is a set of proportionally related sizes that create a visual hierarchy. Spacing is a set of distances that breathe life between elements. Both are aesthetic systems that exist to serve communication and perception. Engineers think in concrete values. "What is the font size?" "What is the margin?" The translation between rhythm-as-concept and pixel-as-value is where handoff disputes accumulate.
Why Scales and Pixels Both Lie
A type scale built on a ratio, say the major third (1.25x), gives a designer a principled set of sizes: 12px, 15px, 19px, 24px, 30px, 37px. The ratio provides visual coherence. But in CSS, these land as non-round pixel values that engineers tend to round to their nearest multiple of 4. The rounding introduces drift. The scale the designer specified in Figma and the scale in the codebase diverge incrementally with every component.
The same problem happens with spacing. Designers use spatial systems based on a base unit, often 4px or 8px, but in practice the Figma file drifts: a card padding that should be 16px was dragged to 15px in a hurry, a gap that should be 24px is 22px because the auto-layout snapped to the wrong value. When an engineer inspects the file and gets 15px, they either implement 15px (inconsistency in the code) or round it to 16px without telling anyone (silent divergence).
Design tokens break this pattern, but only when the token layer is the source of truth for both sides. The designer specifies sizes as token names, not raw values. The engineer reads the token name and emits the CSS custom property. Neither side is interpolating values across the translation boundary.
Structuring a Type Scale as Tokens
A useful type token structure has two layers. The first layer is the scale itself: named size values that correspond to steps in your visual hierarchy.
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 2rem;
--text-4xl: 2.5rem;
The second layer is semantic aliases that map scale steps to roles:
--font-size-caption: var(--text-xs);
--font-size-label: var(--text-sm);
--font-size-body: var(--text-base);
--font-size-subheading: var(--text-lg);
--font-size-heading-3: var(--text-xl);
--font-size-heading-2: var(--text-2xl);
--font-size-heading-1: var(--text-3xl);
--font-size-display: var(--text-4xl);
Components reference the semantic layer. The scale layer can be updated without touching component code, as long as the semantic names stay stable. This is the same two-layer pattern that color tokens use, and it applies equally well to typography.
Line Height Is the Hidden Spacing Token
Teams that carefully token their font sizes often leave line height as a hardcoded value or a ratio specified in the component. This creates a class of spacing bugs that are frustrating to debug: the spacing between elements looks off, but every margin and padding token checks out. The problem is in line height, which adds implicit vertical space that the spatial system did not account for.
Line height should also live in the token file, paired with its corresponding font size:
--leading-tight: 1.25;
--leading-snug: 1.375;
--leading-normal: 1.5;
--leading-relaxed: 1.625;
With semantic aliases that pair with the type scale roles: --leading-body: var(--leading-normal), --leading-heading: var(--leading-tight). When these are set in the token file and consumed by components, the vertical rhythm is deterministic. The spacing system accounts for all sources of vertical space, including the implicit space that line height creates above and below text.
Spatial Systems: Base Unit vs. Named Steps
Two approaches to spacing tokens work in practice. The first is a base-unit system: define a base unit (usually 4px or 8px) and name multiples of it.
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-12: 3rem; /* 48px */
This is the Tailwind spacing model. It works well when the design file is disciplined enough to use only multiples of the base unit. When it is not, you end up with a token for every value in the file, which defeats the point.
The second approach is a named-step system with semantic intent:
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--space-xl: 2rem;
--space-2xl: 3rem;
Named steps are more resilient when the design values are not perfectly aligned to a base unit, because the names communicate intent rather than a specific calculation. A designer can say "this gap is space-md" without counting base units. The engineer implements gap: var(--space-md) and the result is consistent.
The named-step approach is what we recommend for design systems that are in active development, because the values can be refined without renaming the tokens. In a base-unit system, if you decide that your base unit should be 5px instead of 4px, every calculation changes. In a named-step system, you update the value of --space-md and every component that uses it updates automatically.
The Review Process That Actually Works
Handoff disputes over typography and spacing most often happen when the design file and the token file are maintained separately and drift from each other. The fix is making the token file the source of truth before the component is designed, not after.
When a designer adds a new component, the process should be: check whether existing tokens satisfy the spacing and type needs. If yes, use them. If a gap exists, propose a new token before drawing the component with a raw value. The token proposal goes in the token file first, then the component is drawn referencing that token. By the time the engineer implements the component, the token already exists and the implementation is a direct consumption, not an interpretation.
This is a process change as much as a tooling change. DesignVerse supports it by making the token file directly readable during the design process, so the designer can see what tokens are available before reaching for a raw pixel value. The token vocabulary becomes a shared language, not a handoff artifact.