Design tokens vs variables CSS: ¿cuál es la diferencia?
Dos archivos abiertos lado a lado. tokens.json dice
"brand-600": { "$value": "#2563eb", "$type": "color" }; variables.css
dice --color-brand-600: #2563eb;. El mismo valor, casi el mismo nombre — y
la pregunta natural es cuál de los dos se supone que debes escribir.
La respuesta: no son competidores, son fuente y salida. Los design tokens son la fuente — decisiones de diseño guardadas en un archivo neutral respecto a herramientas. Las propiedades personalizadas de CSS son una exportación — las mismas decisiones renderizadas para los navegadores. Una analogía útil viene de los compiladores, y es una analogía: el archivo de tokens es código fuente, la hoja de estilos es un objetivo de compilación, y las Figma Variables o los recursos nativos son objetivos hermanos generados a partir de la misma fuente. La distinción suena académica y no lo es; decide qué puede consumir tus decisiones, qué herramientas pueden comprobarlas y quién revisa qué. El lado de la fuente lo cubrimos a lo largo de nuestra guía de design tokens — este artículo trata de la frontera en sí.
¿A qué pueden llegar los tokens que las variables CSS no?
A lo que no son navegadores. Una propiedad personalizada es una
característica de CSS: llega a todo lo que alcanza una hoja de estilos y nada
más. Las decisiones de un producto llegan más lejos — el mismo azul y el
mismo espaciado tienen que mantenerse en el archivo de Figma, en las apps de
iOS y Android, en las plantillas de correo, en la presentación de diapositivas
que exporta el equipo de ventas. Si variables.css es la fuente de verdad,
cada uno de esos consumidores se alimenta por transcripción manual, y las
copias hechas a mano derivan.
Un archivo de tokens los alimenta a todos como vistas generadas: propiedades personalizadas para la web, Figma Variables para el diseño, recursos de plataforma para el nativo. El día en que aparece un segundo consumidor es el día en que la diferencia deja de ser teórica — con un solo consumidor los dos enfoques son casi indistinguibles; con dos, solo uno de ellos tiene una fuente.
¿Qué sabe un archivo de tokens que una hoja de estilos no?
Significado. Para CSS, --brand-600 es un valor sin tipo que se sustituye
allí donde se usa; nada en el lenguaje sabe que es un color, y una errata
dentro falla en silencio en el momento de usarlo. Un archivo de tokens sabe
más: $type dice que el valor es un color, $description dice para qué
sirve, y una referencia registra que accent está definido como
{color.brand.600} en lugar de ser igual a él por casualidad.
Ese conocimiento es lo que hace funcionar a las herramientas. Una compilación puede validar el archivo — rechazar un color mal formado o una referencia a un token que no existe — antes de que nada se publique. La documentación se puede generar en lugar de escribir. Las transformaciones se pueden aplicar mecánicamente: px a rem, hex a OKLCH, una sola fuente renderizada según las convenciones de cada objetivo. Nada de esto está disponible para una hoja de estilos pelada, porque la hoja de estilos guarda respuestas sin sus preguntas.
¿Cómo se convierte un token en una variable CSS?
Mecánicamente. Tres tokens como fuente DTCG:
{
"color": {
"brand": { "600": { "$value": "#2563eb", "$type": "color" } }
},
"spacing": {
"4": { "$value": "23px", "$type": "dimension" }
},
"semantic": {
"accent": { "$value": "{color.brand.600}", "$type": "color" }
}
}
Y el bloque :root generado a partir de ellos:
:root {
--color-brand-600: #2563eb; /* oklch(0.546 0.215 262.9) */
--spacing-4: 23px;
--color-accent: var(--color-brand-600);
}
Los nombres se convierten en nombres de propiedad, los valores se trasladan
y — el detalle que vale la pena notar — la referencia sobrevive como var():
la exportación preserva la estructura de la decisión, no solo su respuesta
actual. Los componentes consumen entonces la salida con normalidad:
.card {
padding: var(--spacing-4);
background: var(--color-accent);
}
Mira la fuente y las exportaciones lado a lado en Scale Composer — el archivo DTCG en un lado y los mismos nombres renderizados como propiedades personalizadas de CSS, un tema de Tailwind v4 y Figma Variables en el otro; edita la fuente y las tres salidas se mueven juntas.

¿Tienen los tokens y las variables ciclos de vida distintos?
Sí, y la diferencia se nota en la revisión de código. Los tokens son
decisiones de diseño: se
proponen, se revisan, se versionan y se comparan en diffs — un pull request
que cambia accent de un primitivo a otro es un cambio de diseño con forma de
diff revisable, y tanto diseñadores como desarrolladores tienen legitimidad
para comentar. El variables.css generado es detalle de implementación: un
artefacto de compilación que se regenera, no se edita. Editar a mano una hoja
de estilos generada tiene la misma vida útil que editar a mano cualquier
salida compilada — hasta la siguiente compilación.
La regla práctica que se desprende: revisa la fuente, genera el objetivo, y no dejes entrar en la hoja de estilos ningún valor que no haya pasado por la fuente.
¿Cuándo bastan honestamente las variables CSS por sí solas?
Cuando hay un solo consumidor y puede que nunca haya más que uno. Un producto
web de una sola plataforma sin handoff a Figma, mantenido por quienes lo
escribieron, pierde poco declarando sus propiedades personalizadas
directamente — el archivo es más simple, la cadena de herramientas más corta,
y un bloque :root disciplinado con propiedades nombradas por rol captura
buena parte del beneficio de los nombres sin ninguna infraestructura de
tokens. Esa es una elección legítima, no una inferior.
La capa de tokens justifica su coste cuando los consumidores se multiplican: la primera biblioteca de Figma que debe coincidir con el código, la primera superficie nativa, el primer segundo tema. Adoptar la maquinaria antes de eso es pagar por un alcance que aún no usas — razonable como preparación, pero no obligatorio.
¿Qué añaden las variables CSS en tiempo de ejecución?
Una cosa que los tokens por sí solos no pueden: la re-resolución en vivo en el navegador. Las propiedades personalizadas se resuelven a través de la cascada — la mecánica está documentada en la guía de MDN sobre propiedades personalizadas de CSS — así que redeclararlas bajo un ámbito cambia todos los consumidores a la vez, sin recompilar nada:
[data-theme="dark"] {
--color-accent: oklch(0.70 0.14 262.9); /* valor oscuro re-derivado */
}
Cada var(--color-accent) de la página se vuelve a resolver en el momento en
que el atributo aparece. Esto es una propiedad del formato de salida, no de la
fuente — una razón por la que la exportación a CSS es el objetivo correcto
incluso cuando los tokens son la fuente, y el mecanismo sobre el que se
construyen los sistemas de temas. Qué valores debe tener el tema oscuro es
un tema aparte; aquí basta con que el
cambio cueste un solo bloque de declaración.
Genera tus variables a partir de una fuente
La frontera se ve más clara cuando la cruzas a propósito. Exporta propiedades personalizadas de CSS a partir de una fuente de tokens — cambia una decisión en el lado de la fuente (un color semilla, un paso de la escala), vuelve a exportar y lee el diff en el lado del CSS: las variables se actualizan, la estructura de referencia se mantiene, y nada necesitó edición a mano.