Design token vs variabili CSS vs Tailwind: cosa risolve ognuno
Design token, variabili CSS e Tailwind vengono confusi nei dibattiti sullo stack 2026. Stanno su tre livelli diversi e la scelta non è quasi mai aut aut.
Un design token è la registrazione platform-agnostic di una decisione di design (un colore, uno step di spacing, un raggio) salvata in un formato strutturato che può compilarsi in CSS, Swift, Kotlin, XML o in un theme di Tailwind. Le variabili CSS sono la primitiva nativa del browser che tiene quei valori a runtime. Tailwind è un framework di utility che, dalla versione 4, genera classi a partire dalle variabili CSS dichiarate in un blocco theme. I tre stanno su tre livelli diversi dello stesso stack e il confronto ha senso solo quando smetti di trattarli come alternative.
Questo articolo è per i team di prodotto che stanno per scegliere un'architettura di styling per un nuovo SaaS o stanno valutando una migrazione. Mappiamo i tre concetti al livello che occupano davvero, elenchiamo dove ognuno è lo strumento giusto, nominiamo i failure mode che nascono dal confonderli e chiudiamo con la scelta che facciamo in Studio e perché.
TL;DR per chi ha fretta
Scegli i design token (in formato W3C DTCG) quando più di una piattaforma deve consumare le stesse decisioni di design, quando il team di design lavora in Figma con Tokens Studio o quando vuoi un'unica fonte di verità che sopravviva a un cambio di framework. Usa le variabili CSS come implementazione runtime di quei token per il web. Vai su Tailwind quando il team valorizza velocità e un vocabolario di utility condiviso su una superficie piccola o media, e accetta che la v4 lo ha reso un sottile strato sopra le tue variabili CSS invece di un sistema parallelo. Salta Tailwind quando il progetto porta un design system maturo, gira su molte app consumer o misura ogni kilobyte di CSS spedito.
I tre livelli, in modo piano
I design token sono un formato, non una feature
Il W3C Design Tokens Community Group (DTCG) ha pubblicato la prima versione stabile del Design Tokens Format Module il 28 ottobre 2025. Il formato è JSON, le proprietà sono prefissate con $ e i file usano l'estensione .tokens o .tokens.json con media type application/design-tokens+json. Un file di token è un documento vendor-neutral che qualunque tool compatibile (Figma, Penpot, Sketch, Framer, Knapsack, Supernova, zeroheight, Tokens Studio, Style Dictionary, Terrazzo) può leggere o scrivere.
{
"color": {
"brand": {
"primary": { "$type": "color", "$value": "#3D5AFE" }
}
},
"radius": {
"md": { "$type": "dimension", "$value": "8px" }
}
}Quel file da solo non fa nulla. Un build tool (Style Dictionary è l'implementazione di riferimento, Terrazzo è lo sfidante moderno) lo compila in qualsiasi cosa serva al target: custom properties CSS per il web, una extension Swift per iOS, un object Kotlin per Android, un modulo JS per React Native, un theme Tailwind. Il token sta a monte di ogni implementazione.
Le variabili CSS sono il runtime web
Le custom properties CSS (nome di specifica; tutti dicono variabili CSS) sono soggette alla cascata, possono essere sovrascritte su qualsiasi selettore e lette da qualunque proprietà che accetti quel tipo di valore. Sono l'unico meccanismo nel browser che permette a una singola dichiarazione di essere tematizzata, scambiata a runtime o letta da JavaScript senza ricompilare.
:root {
--color-brand-primary: #3D5AFE;
--radius-md: 8px;
}
[data-theme="dark"] {
--color-brand-primary: #8C9EFF;
}
.button {
background: var(--color-brand-primary);
border-radius: var(--radius-md);
}Se hai mai spedito un dark mode funzionante senza un build step, hai usato variabili CSS. Non sono un design system, sono il filo fra i tuoi token e i pixel.
Tailwind è un framework che consuma variabili CSS
Tailwind CSS v4, rilasciato a inizio 2025, ha riscritto l'engine in Rust (Oxide), rimosso il file di config JavaScript e spostato il design system in un blocco CSS-native @theme. I valori che dichiari in @theme diventano sia variabili CSS sia la sorgente per le utility class generate.
@import "tailwindcss";
@theme {
--color-brand-primary: #3D5AFE;
--radius-md: 8px;
}
/* genera: bg-brand-primary, text-brand-primary, rounded-md, ecc. */Il cambio conta. In v3, i design token vivevano in tailwind.config.js ed erano intrappolati nel build step. In v4 vivono come variabili CSS reali che DevTools può leggere e altro CSS può referenziare. Tailwind è diventato un generatore di utility sopra variabili che controlli tu, invece di un ecosistema parallelo.
Tabella di confronto
DimensioneDesign token (DTCG)Variabili CSSTailwind v4LivelloSorgente di veritàRuntime browserGeneratore di utilityDove vivonoFile JSON (.tokens.json)Dentro al CSS, scoped a selettoriBlocco @theme in CSSCross-platformSì (web, iOS, Android, RN)Solo webSolo webTheming a runtimeTramite variabili CSS compilateNativo, senza rebuildNativo via variabili sottostantiAdatto ai designerSì (i plugin Figma leggono DTCG)No, territorio devParziale, richiede dimestichezza con le utilityBuild stepRichiesto (Style Dictionary, Terrazzo)NessunoRichiesto (compiler Tailwind)Rischio lock-inBasso, spec vendor-neutralNessuno, standard webMedio, sintassi specifica del frameworkPeso in outputQuel che compiliByte che scriviSolo le utility che usi davveroDove vincono i design token
I token si guadagnano il posto nel momento in cui entra in scena una seconda piattaforma. Un'app iOS nativa che deve condividere i colori brand con il web non può consumare CSS, ma può consumare un build di Style Dictionary che emette un file Swift dallo stesso JSON che consuma il web. Un team di design che lavora in Figma con Tokens Studio scrive DTCG nativamente; senza quel livello, ogni aggiornamento del brand diventa un port manuale. I SaaS multi-brand o multi-tenant ne traggono lo stesso vantaggio: ogni tenant spedisce un set di token, Style Dictionary compila bundle di variabili CSS per tenant, il runtime resta identico.
I token agiscono anche come contratto fra design ed engineering che non dipende dalle mode di tooling. Il fatto che il formato DTCG abbia raggiunto lo stato stabile a fine 2025 significa che un file di token scritto oggi dovrebbe ancora essere parsabile fra cinque anni, indipendentemente da quale framework gestisca il frontend.
Dove vincono le variabili CSS
Le variabili CSS vincono il runtime. Sono l'unico modo sano per spedire dark mode, density mode, theme di brand o skin per tenant senza rebuild. Sono a zero dipendenze, zero build e supportate in ogni browser che conta. Leggere una variabile da JavaScript con getComputedStyle funziona senza file di config. Sovrascrivere una variabile in una media query scambia i token senza toccare il markup.
Per un piccolo sito di marketing o un prodotto a brand singolo senza integrazioni con tool di design, le sole variabili CSS spesso bastano: scrivile in un blocco :root, documentale in un README, spedisci. Il formato DTCG diventa overhead se non esiste un secondo consumatore.
Dove vince Tailwind
Tailwind si guadagna il posto quando velocità di team e vocabolario condiviso contano più dell'architettura CSS. Un piccolo team che prototipa un nuovo prodotto può muoversi più in fretta con classi utility che con un design system custom, perché il costo di nominare i componenti è zero. La v4 ha aggiunto il bridge @theme, quindi i token che dichiari sono accessibili anche al CSS non-Tailwind, il che toglie il peggio del lock-in di v3.
Tailwind spedisce anche un set di token di default rispettabile (scala di spacing, ramp di colori in OKLCH, scala tipografica) su cui un team junior può appoggiarsi mentre impara. Per siti vetrina, tool interni e prodotti senza un design system formale, Tailwind è un default difendibile.
I tre failure mode dal confonderli
Trattare Tailwind come un design system
Tailwind genera utility. Non impone naming semantico, non documenta i contratti dei componenti, non audita l'uso scorretto dei token su più progetti consumer. Un team che chiama Tailwind il proprio design system tende a spedire valori hardcoded dentro le classi utility (bg-[#3D5AFE], p-[17px]) entro pochi mesi. Il fix è vietare gli arbitrary value nel lint, dichiarare ogni valore in @theme e trattare il blocco theme come il registro dei token.
Saltare il livello dei token perché ci sono le variabili CSS
Un team che va dritto da Figma alle variabili CSS perde l'unico artefatto che sopravvive a una migrazione di framework. Il file CSS è l'implementazione, non la sorgente. Quando arriva la seconda piattaforma (app mobile, sync col tool di design, brand partner), il team torna a fare port manuali. Il fix è scrivere prima il JSON dei token anche se l'unico consumer di oggi è il web; Style Dictionary si configura in poche ore.
Trattare i token come una copia JSON del CSS
Token che fanno mirror uno a uno del CSS (color-blue-500 in JSON, --color-blue-500 in CSS) mancano il punto. I token portano significato semantico (color.action.primary, color.surface.elevated) che mappa su molti valori concreti su più theme e piattaforme. Una palette di colori piatta in JSON è una palette di colori, non un sistema di token.
Cosa usiamo in Studio e perché
Studio gestisce un design system interno che si spedisce come pacchetto NPM e alimenta più di una dozzina di progetti consumer. Definiamo i token in JSON, li compiliamo in variabili CSS (il namespace --ds-*) con un build di Style Dictionary e li consumiamo in CSS Modules e CSS dei componenti. Abbiamo rimosso Tailwind dalla produzione tre anni fa, dopo che ha superato il 50% del peso del bundle in un progetto che doveva tenere LCP sotto 1s ovunque.
La ragione non era estetica. Era che il design system già imponeva i nomi, documentava ogni contratto di componente e poteva fare lint sull'uso scorretto dei token su tutti i progetti consumer da un manifest centrale. Tailwind diventava un sistema di naming parallelo che diluiva il contratto. Per nuovo lavoro client dove non c'è un design system interno su cui appoggiarsi e il progetto si spedisce in settimane, raccomandiamo ancora Tailwind v4 con un blocco @theme stretto e il lint sugli arbitrary value disabilitato.
L'albero decisionale che applichiamo: più di una piattaforma, oppure tool di design che parlano DTCG nativamente, oppure theming a runtime fra tenant, allora il livello dei token JSON non è negoziabile. Solo web, brand singolo, maturità del design system sopra i tre anni, allora le variabili CSS compilate dai token bastano. Solo web, nessun design system, team sotto le cinque persone che spedisce in settimane, allora Tailwind v4 con disciplina sui token è la via difendibile più rapida.
Domande frequenti
- Do I still need design tokens if I use Tailwind v4?
- Only if a second consumer exists. Tailwind v4 already turns your @theme block into CSS variables, which is enough for a single-platform product. The moment a native mobile app, a partner brand, or a Figma sync needs to read the same values, you need the JSON token layer above Tailwind. The JSON file becomes the source; Tailwind becomes one compiled output.
- Can I migrate from Tailwind v3 to design tokens without rewriting components?
- Mostly yes. Move the values from tailwind.config.js into a DTCG JSON file, run Style Dictionary to emit CSS variables and a Tailwind v4 @theme block, and ship both. Components that reference Tailwind utilities keep working; components that reference CSS variables work too. The migration cost is in the build setup, not the components.
- Are CSS variables slow at scale?
- No. CSS custom properties are evaluated by the browser engine in C++, not in user JavaScript, and are heavily optimized. The performance concerns from 2017 era benchmarks were resolved by every major engine. The real cost in modern stacks is bundle size of the CSS file, not runtime variable resolution.
Studio
Inizia un progetto.
Un partner unico per aziende, PA, startup e SaaS. Produzione più veloce, tecnologie moderne, costi ridotti. Un team, una fattura.