The dimension type, quickly
In the DTCG spec (Format Module 2025.10), the dimension type represents a distance in a single UI dimension: width, height, radius, thickness, spacing. The value is always an object with a numeric value and a unit (either px or rem).
A dimensional scale is the backbone of spatial consistency: the structure that connects your spacing, sizing, and typographic dimensions into a coherent system instead of a bag of magic numbers.
Every design system has a moment where someone opens the tokens file and finds spacing-1, spacing-2, spacing-3 … spacing-12. Twelve steps, no explanation of the logic behind them, and a comment that says // do not change. That’s not a scale. That’s a list someone wrote down once and nobody questioned since.
{
"spacing-base": {
"$type": "dimension",
"$value": { "value": 16, "unit": "px" },
"$description": "Base unit for all spacing calculations"
}
}
No shorthand strings. No bare numbers. The spec is explicit about this: value and unit travel together. That rigidity is the point: it removes ambiguity when tokens cross tool boundaries.
What makes a scale a scale
A scale is not just “a bunch of tokens with incrementing names”. A scale has three properties:
A base value — the anchor everything else derives from.
A ratio or progression — the mathematical relationship between steps.
A bounded range — a deliberate start and end, not an open-ended list.
Without all three, you have a collection. Collections grow unchecked. Scales don’t.
Building a spacing scale with groups
The DTCG spec’s group features make scales cleaner to express. You set $type at the group level so every child inherits it, and you can use $root to define the base value right inside the group.
{
"spacing": {
"$type": "dimension",
"$description": "4px base, doubling progression",
"$root": {
"$value": { "value": 16, "unit": "px" },
"$description": "Default spacing — use when no specific scale step fits"
},
"2xs": {
"$value": { "value": 2, "unit": "px" },
"$description": "Minimal spacing, e.g. between icon and label"
},
"xs": {
"$value": { "value": 4, "unit": "px" },
"$description": "Tight spacing for compact UI"
},
"sm": {
"$value": { "value": 8, "unit": "px" },
"$description": "Small gaps, inline elements"
},
"md": {
"$value": { "value": 16, "unit": "px" },
"$description": "Standard content spacing"
},
"lg": {
"$value": { "value": 32, "unit": "px" },
"$description": "Section-level spacing"
},
"xl": {
"$value": { "value": 64, "unit": "px" },
"$description": "Major layout divisions"
}
}
}
Notice: $root gives the group a default value at {spacing.$root} without polluting the named scale. If a consumer just needs “the standard spacing”, they reference the root. If they need a specific step, they pick from the scale. Two access patterns, one group.
Naming conventions that survive
Three naming strategies show up in the wild, and each has trade-offs.
T-shirt sizes (xs, sm, md, lg, xl) are readable and naturally bounded. You can only stretch the metaphor so far before 4xlstarts feeling ridiculous. That ceiling is a feature. When someone needs 5xl, it’s a signal the scale needs redesigning, not extending.
Numeric multipliers (space-1, space-2, space-4, space-8) map directly to the math. space-4 on a 4px base is 16px. You can do the calculation in your head. The downside: they invite unbounded growth. There’s no natural stopping point between space-1 and space-100.
Semantic names (space-inset, space-stack, space-inline) encode intent instead of magnitude. They work well as an alias layer on top of a numeric scale, but as your only scale they become a naming negotiation every time a new pattern appears.
The strongest approach in design systems I’ve seen reviewed is a bounded base scale with t-shirt or numeric names, plus a thin semantic alias layer for recurring patterns. Two tiers, clear responsibilities.
Scaling typography dimensions
Typographic scales follow the same principles but add a wrinkle: the progression is often non-linear. A modular scale with a ratio of 1.25 (Major Third) produces steps like 12.8, 16, 20, 25, 31.25—not round numbers, but mathematically coherent.
With DTCG tokens, you model this as individual dimension tokens that feed into composite typography tokens:
{
"font-size": {
"$type": "dimension",
"$description": "Major Third scale (1.25), base 16px",
"sm": {
"$value": { "value": 0.8, "unit": "rem" },
"$description": "Captions, helper text"
},
"md": {
"$value": { "value": 1, "unit": "rem" },
"$description": "Body text"
},
"lg": {
"$value": { "value": 1.25, "unit": "rem" },
"$description": "Subheadings"
},
"xl": {
"$value": { "value": 1.563, "unit": "rem" },
"$description": "Section headings"
},
"2xl": {
"$value": { "value": 1.953, "unit": "rem" },
"$description": "Page headings"
}
}
}
Using rem here is deliberate: font sizes should respect user preferences. Spacing tokens in px are a different conversation (and a reasonable default for layout), but font sizes in px are a choice that locks out users who’ve changed their browser defaults.
Cross-referencing scales with aliases
The most common way to connect scales is curly-brace aliases. A token’s $value can point at another token by name, and any update to the source propagates automatically.
{
"base": {
"spacing": {
"$type": "dimension",
"$value": { "value": 16, "unit": "px" }
}
},
"layout": {
"compact": {
"$type": "dimension",
"$value": "{base.spacing}",
"$description": "Alias of base.spacing — stays in sync"
}
}
}
Here layout.compact is an alias for base.spacing: same value, same unit, kept in sync. This is the workhorse pattern for keeping scales aligned across spacing and typography without duplicating numbers.
Curly-brace references always point to a whole token. If you need to borrow only one part — say, the number 16 from base.spacing but with a different unit — the newer DTCG spec (Format Module 2025.10) adds property-level references via $ref using JSON Pointer syntax. It’s a powerful escape hatch, but tool support is still catching up, so reach for it only when a plain alias won’t do.
The common mistakes
Scales without a base. Five values that don’t relate to each other arithmetically. They’re just five numbers someone picked. When the sixth need appears, there’s no logic to guide the choice.
Scales that leak implementation. spacing-16px as a token name defeats the purpose. If you rename the value, the name lies. Encode the role or the scale position, never the output.
One scale for everything. Spacing, sizing, and border-radius have different ranges and different progressions. A 4px base with a doubling ratio works for spacing. It produces absurd values for border-radius. Each dimensional property needs its own scale, or at minimum its own subset of a shared one.
No $description fields. A scale step called md means nothing in isolation. "Standard content spacing" tells a developer exactly when to use it. DTCG supports $description on every token. Use it.
Dimensional scales are where a design system stops being a style guide and starts being an engineering tool. The math doesn’t have to be complex (a base value, a clear ratio, and a finite number of steps). But it has to be intentional. A scale you can explain in one sentence is a scale your team will actually follow.
Design Tokens Pills is a newsletter about practical design token architecture.


