Design Systems · · 12 min read
Semantic tokens: the only sensible way to do design systems in 2026
Aliases aren't enough. You need a semantic hierarchy that survives dark mode, theming, and multi-brand. Here's how to build it from first principles — not from tooling.
I’ve seen design systems die for many reasons. Lack of governance. Team turnover. Partial adoption by engineers. But over the past two years I’ve identified a recurring pattern in the ones that collapse fastest: they have flat tokens, no semantics, built to look organized without actually being so.
A file with 200 CSS variables named --color-blue-500, --color-blue-600, and so on is not a design system. It’s a palette with a different name. And when the request comes in to support dark mode, a second brand, or a low-vision accessibility theme, that file becomes a serious problem.
The three-tier hierarchy that works
The model I use across all my enterprise projects has three distinct tiers, with separate responsibilities and clear dependency rules.
Tier 1 — Primitives. These are raw values: exact colors, sizes, typefaces, durations. They carry no semantic meaning. They are the raw vocabulary of the system. Primitive tokens are never used directly in components — they exist only to be referenced by the next tier.
Tier 2 — Semantic tokens. This is where the magic happens. Semantic tokens map primitives to interface meanings. They don’t describe a color — they describe a function: --color-background-default, --color-text-primary, --color-border-subtle. In dark mode, the value of --color-background-default changes, but every component using that token updates automatically — without touching a single component file.
Tier 3 — Component tokens. Specific to a single component or pattern. --button-primary-background points to --color-action-primary, which in turn points to the correct primitive for the active theme. This tier is optional for small systems, but becomes indispensable with multi-brand.
The problem with aliases that lack semantics
Many teams implement something that looks like a three-tier system but is really just one tier deep. An alias like --brand-primary: var(--color-blue-600) is not a semantic token — it’s an alias. It doesn’t describe a function in the interface; it just gives a specific color a shorter name.
If I have to explain what a token does, the name is wrong.
The difference becomes clear the moment you try to build an alternative theme. If a button uses --brand-primary as its background, what happens when the second brand uses red as its primary color? The correct semantic token is --color-action-primary-background: it describes the function, the role, and can be mapped to any primitive in any theme without breaking anything.
A practical naming structure
The naming convention I use follows this pattern: category — property — variant — state. Not every segment is always needed, but the order is always the same.
--color-background-default— category: color, property: background, variant: default--color-text-on-primary— text sitting on top of a primary-background element--color-border-focus— border in the focus state (for WCAG accessibility)--size-spacing-md— medium-scale spacing--duration-interaction-fast— duration for quick interactions
The guiding principle is that a semantic token name should be readable by a designer and a developer alike, without any additional context.
Dark mode without overriding everything
The practical payoff of a semantic hierarchy shows up most clearly with dark mode. Instead of overriding every individual CSS variable with hundreds of exceptions, you only redefine the mapping between semantic tokens and primitives.
Components don’t change — they always reference the same semantic token. The dark theme is simply a substitution layer at Tier 2, not a rewrite of component CSS. With this approach, on a system with 60 components, the dark theme CSS takes fewer than 80 lines.
Multi-brand in production
On the Exein project I had to manage three brands with very different visual identities on the same component system. The solution was to build semantic tokens in a brand-neutral way — they describe functions, not identities — and author a separate theme file for each brand.
A well-designed semantic token has no idea which brand it belongs to. It only knows what it needs to do in the interface.
The practical result: adding a fourth brand took less than half a day. Create a primitives file, map it to the existing semantic tokens, verify WCAG contrast ratios. Zero changes to components.
Tooling in 2026
Token Studio for Figma remains the reference for the design-to-development bridge. Amazon’s Style Dictionary is the most flexible tool for distributing tokens as CSS, JSON, Swift, and Kotlin. But the choice of tooling comes after the choice of architecture. A poorly designed system doesn’t become a good one by switching software.
