All articles Design Systems

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.

If you're redesigning your design system or building one from scratch, I can help you establish the right structure before it becomes too costly to change.

Ho visto i design system morire per molte ragioni. Mancanza di governance. Ricambio del team. Adozione parziale da parte degli ingegneri. Ma negli ultimi due anni ho identificato un pattern ricorrente in quelli che crollano più velocemente: hanno token piatti, nessuna semantica, costruiti per sembrare organizzati senza esserlo davvero.

Un file con 200 variabili CSS chiamate --color-blue-500, --color-blue-600 e così via non è un design system. È una palette con un altro nome. E quando arriva la richiesta di supportare il dark mode, un secondo brand o un tema di accessibilità per ipovedenti, quel file diventa un problema serio.

La gerarchia a tre livelli che funziona

Il modello che uso in tutti i miei progetti enterprise ha tre livelli distinti, con responsabilità separate e regole di dipendenza chiare.

Livello 1 — Primitivi. Sono valori grezzi: colori esatti, dimensioni, font, durate. Non portano nessun significato semantico. Sono il vocabolario grezzo del sistema. I token primitivi non vengono mai usati direttamente nei componenti — esistono solo per essere referenziati dal livello successivo.

Livello 2 — Token semantici. Qui avviene la magia. I token semantici mappano i primitivi ai significati dell'interfaccia. Non descrivono un colore — descrivono una funzione: --color-background-default, --color-text-primary, --color-border-subtle. In dark mode, il valore di --color-background-default cambia, ma ogni componente che usa quel token si aggiorna automaticamente — senza toccare un singolo file di componente.

Livello 3 — Token di componente. Specifici per un singolo componente o pattern. --button-primary-background punta a --color-action-primary, che a sua volta punta al primitivo corretto per il tema attivo. Questo livello è opzionale per sistemi piccoli, ma diventa indispensabile con il multi-brand.

Il problema degli alias privi di semantica

Molti team implementano qualcosa che sembra un sistema a tre livelli ma è in realtà un solo livello di profondità. Un alias come --brand-primary: var(--color-blue-600) non è un token semantico — è un alias. Non descrive una funzione nell'interfaccia; dà solo a un colore specifico un nome più corto.

Se devo spiegare cosa fa un token, il nome è sbagliato.

La differenza emerge nel momento in cui si prova a costruire un tema alternativo. Se un pulsante usa --brand-primary come sfondo, cosa succede quando il secondo brand usa il rosso come colore primario? Il token semantico corretto è --color-action-primary-background: descrive la funzione, il ruolo, e può essere mappato su qualsiasi primitivo in qualsiasi tema senza rompere nulla.

Una struttura di naming pratica

La convenzione di naming che uso segue questo pattern: categoria — proprietà — variante — stato. Non ogni segmento è sempre necessario, ma l'ordine è sempre lo stesso.

  • --color-background-default — categoria: colore, proprietà: sfondo, variante: default
  • --color-text-on-primary — testo posizionato sopra un elemento con sfondo primario
  • --color-border-focus — bordo nello stato di focus (per l'accessibilità WCAG)
  • --size-spacing-md — spaziatura a scala media
  • --duration-interaction-fast — durata per interazioni rapide

Il principio guida è che il nome di un token semantico deve essere leggibile da un designer e da uno sviluppatore allo stesso modo, senza nessun contesto aggiuntivo.

Dark mode senza sovrascrivere tutto

Il beneficio pratico di una gerarchia semantica emerge più chiaramente con il dark mode. Invece di sovrascrivere ogni singola variabile CSS con centinaia di eccezioni, si ridefinisce solo il mapping tra token semantici e primitivi.

I componenti non cambiano — referenziano sempre lo stesso token semantico. Il tema scuro è semplicemente un layer di sostituzione al livello 2, non una riscrittura del CSS dei componenti. Con questo approccio, su un sistema con 60 componenti, il CSS del tema scuro occupa meno di 80 righe.

Multi-brand in produzione

Nel progetto Exein ho dovuto gestire tre brand con identità visive molto diverse sullo stesso sistema di componenti. La soluzione è stata costruire i token semantici in modo brand-neutral — descrivono funzioni, non identità — e creare un file di tema separato per ciascun brand.

Un token semantico ben progettato non sa a quale brand appartiene. Sa solo cosa deve fare nell'interfaccia.

Il risultato pratico: aggiungere un quarto brand ha richiesto meno di mezza giornata. Creare un file di primitivi, mapparlo sui token semantici esistenti, verificare i rapporti di contrasto WCAG. Zero modifiche ai componenti.

Il tooling nel 2026

Token Studio per Figma rimane il riferimento per il ponte design-sviluppo. Style Dictionary di Amazon è lo strumento più flessibile per distribuire i token come CSS, JSON, Swift e Kotlin. Ma la scelta del tooling viene dopo la scelta dell'architettura. Un sistema mal progettato non diventa buono cambiando software.

Se stai ridisegnando il tuo design system o stai costruendone uno da zero, posso aiutarti a stabilire la struttura giusta prima che diventi troppo costoso cambiarla.

Keep reading