Nunca hardcodearías una cadena de conexión a base de datos en 47 archivos diferentes. Entonces, ¿por qué los equipos frontend siguen hardcodeando #3b82f6 en 200 lugares de sus hojas de estilo? Los design tokens resuelven este problema de la misma manera que la configuración lo resuelve en el backend: una única fuente de verdad, referenciada en todas partes, cambiada en un solo lugar.
Los design tokens son los átomos visuales de un sistema de diseño. Almacenan decisiones — no solo valores — sobre color, tipografía, espaciado, sombras, bordes y animaciones en un formato que cualquier componente puede consumir. Junto con la metodología Atomic Design, forman la base de toda arquitectura de componentes escalable.
Los design tokens son los átomos visuales de diseño del sistema de diseño — específicamente, son entidades con nombre que almacenan atributos de diseño visual.
Por qué los Design Tokens importan
Sin tokens, las decisiones de diseño están dispersas en archivos CSS, estilos de componentes y estilos inline. Un “azul de marca” podría ser #2563eb en el header, #3b82f6 en botones y #1d4ed8 en enlaces — tres azules diferentes que deberían ser el mismo. Los tokens eliminan esta deriva estableciendo un único valor canónico.
Cuando actualizas un token, cada componente que lo referencia se actualiza automáticamente. Cambia --color-primary una vez, y tus botones, enlaces, encabezados, anillos de focus y estados activos siguen. Esta es la promesa fundamental de un sistema de diseño — y puedes ver este principio aplicado en la práctica en nuestro artículo sobre Atomic Design con más de 45 componentes.
Categorías de Tokens
Tu paleta completa de colores — desde primarios de marca y neutros hasta colores semánticos para estados de éxito, advertencia, error e información. Los tokens semánticos como --color-text y --color-bg se adaptan entre modos claro y oscuro sin cambiar código de componentes. Define tokens primitivos (la paleta cruda) y tokens semánticos (el significado) por separado.
Un sistema de rejilla de 8 puntos asegura un ritmo espacial consistente. Valores como --space-1 (4px) hasta --space-12 (96px) crean layouts armoniosos. Los componentes nunca usan valores de píxeles arbitrarios — cada margin, padding y gap referencia un token de espaciado. Esto elimina el debate de si son 14px o 16px para siempre.
Familias de fuentes, tamaños, pesos, alturas de línea y espaciado de letras — todo tokenizado. Las escalas de tipografía fluida usan clamp() para asegurar texto legible desde móvil hasta ultrawide. Un encabezado que mide 2rem en móvil crece suavemente a 3rem en escritorio sin media queries.
Sombras, radios de borde, transiciones y animaciones. Sombras consistentes (--shadow-sm, --shadow-md, --shadow-lg) crean jerarquía de profundidad. Tokens de transición (--transition-fast: 150ms, --transition-base: 300ms) aseguran una sensación de animación uniforme. Los tokens de border-radius previenen el problema de que algunos botones tienen 4px y otros 8px.
Arquitectura de Tokens: Tres Capas
Los design tokens funcionan mejor organizados en tres capas: primitiva, semántica y de componente. Cada capa añade significado.
Los tokens primitivos son los valores crudos — tu paleta. No tienen significado adjunto, solo nombres y valores. --blue-500: #3b82f6, --gray-100: #f3f4f6, --space-4: 1rem. Nunca los usas directamente en componentes. Son los bloques de construcción para los tokens semánticos.
Los tokens semánticos asignan significado a los primitivos. --color-primary: var(--blue-500), --color-bg: var(--gray-100), --color-text: var(--gray-900). Los componentes usan tokens semánticos exclusivamente. Así funciona el modo oscuro: intercambias los valores primitivos detrás de los tokens semánticos, y cada componente se adapta.
Los tokens de componente (opcionales) son alias para componentes específicos. --btn-bg: var(--color-primary), --btn-text: var(--color-on-primary), --card-radius: var(--radius-md). Añaden una capa extra de flexibilidad: puedes cambiar todos los fondos de botones sin afectar otros componentes que usan --color-primary.
Implementación en CSS
/* tokens/primitives.css — paleta cruda, nunca usar directamente */
:root {
--blue-50: #eff6ff;
--blue-500: #3b82f6;
--blue-600: #2563eb;
--blue-700: #1d4ed8;
--gray-50: #f9fafb;
--gray-100: #f3f4f6;
--gray-700: #374151;
--gray-900: #111827;
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
} /* tokens/semantic.css — nombres con significado, usados en componentes */
:root {
--color-primary: var(--blue-600);
--color-primary-hover: var(--blue-700);
--color-bg: var(--gray-50);
--color-bg-alt: var(--gray-100);
--color-text: var(--gray-900);
--color-text-light: var(--gray-700);
--font-size-base: 1rem;
--font-size-lg: 1.25rem;
--font-size-xl: 1.5rem;
--radius-sm: 0.25rem;
--radius-md: 0.5rem;
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
--transition-fast: 150ms ease;
--transition-base: 300ms ease;
} /* Modo oscuro — intercambia primitivos detrás de tokens semánticos */
[data-theme="dark"] {
--color-primary: var(--blue-500);
--color-primary-hover: var(--blue-600);
--color-bg: var(--gray-900);
--color-bg-alt: var(--gray-700);
--color-text: var(--gray-50);
--color-text-light: var(--gray-100);
--shadow-sm: 0 1px 2px rgba(0,0,0,0.3);
--shadow-md: 0 4px 6px rgba(0,0,0,0.4);
}
/* Los componentes usan los mismos tokens — cero cambios de código */ Tokens vs. Alternativas
| Enfoque | Mantenibilidad Recommended | Modo Oscuro | Rendimiento |
|---|---|---|---|
| CSS Custom Properties | Excelente | Intercambio nativo | Cero runtime |
| Tailwind Utility Classes | Buena | Basado en config | Purge necesario |
| CSS-in-JS (styled-components) | Moderada | Theme provider | Coste runtime |
| Variables SCSS | Moderada | Duplicación manual | Solo build-time |
| Valores hardcodeados | Terrible | Imposible | N/A |
Configurar tu sistema de tokens
Guía de implementación de tokens
- Auditar estilos existentes
Busca en tu código valores de color hardcodeados, espaciados en píxeles y declaraciones de fuentes. Lista cada valor único — probablemente encontrarás duplicados y casi-duplicados que deberían consolidarse.
- Definir tokens primitivos
Crea tu paleta cruda en tokens/primitives.css. Colores (escalas completas como blue-50 hasta blue-900), espaciado (incrementos de 4px), tamaños de fuente, familias y pesos.
- Crear tokens semánticos
Mapea primitivos a nombres significativos en tokens/semantic.css. --color-primary, --color-text, --color-bg, --color-error, --color-success. Estos son los que tus componentes usarán realmente.
- Reemplazar valores hardcodeados
Recorre cada componente y reemplaza valores crudos con referencias a tokens. color: #3b82f6 se convierte en color: var(--color-primary). padding: 16px se convierte en padding: var(--space-4).
- Añadir modo oscuro
Crea un bloque [data-theme="dark"] que reasigne tokens semánticos a diferentes primitivos. Alterna el atributo data-theme en <html> con un pequeño script. Cada componente se adapta automáticamente.
Estructura de archivos de tokens
src/styles/
├── global.css → Importa todos los archivos de tokens, resets base
└── tokens/
├── primitives.css → Paleta cruda (colores, escalas)
├── semantic.css → Nombres con significado (modo claro por defecto)
├── dark.css → Overrides de modo oscuro
├── typography.css → Familias, tamaños, pesos, alturas de línea
├── spacing.css → Valores de rejilla de 8 puntos
└── effects.css → Sombras, radios, transiciones
El poder de los tokens en cascada
Uno de los patrones más poderosos son los overrides contextuales de tokens. Como las CSS custom properties cascadean, puedes sobrescribir tokens en contextos específicos:
/* Una card oscura sobrescribe tokens para sus hijos */
.card--dark {
--color-bg: var(--gray-900);
--color-text: var(--gray-50);
--color-primary: var(--blue-400);
}
/* Todos los hijos (encabezados, texto, enlaces) se adaptan automáticamente */ /* Ajustar tokens de espaciado para móvil */
@media (max-width: 768px) {
:root {
--space-section: var(--space-6); /* 24px en lugar de 48px */
--font-size-hero: var(--font-size-xl); /* texto hero más pequeño */
}
} /* Una sección hero con tratamiento visual diferente */
.hero {
--color-bg: var(--color-primary);
--color-text: white;
}
/* Todos los organismos dentro del hero heredan estos overrides */ Beneficios a escala
Cada componente dibuja de la misma paleta. No más conversaciones de ¿cuál azul era ese?
Intercambia valores de tokens en un archivo. Cada componente se adapta sin modificaciones.
Aplica ratios de contraste a nivel de token. --color-text sobre --color-bg siempre cumple WCAG 4.5:1.
La rejilla de 8 puntos elimina espaciados arbitrarios. Cada layout tiene ritmo consistente y espacio para respirar.
Cambiar toda la identidad visual significa actualizar un archivo de tokens. Sin cambios en componentes necesarios.
Los nombres de tokens en código coinciden con los de Figma. Diseñadores y desarrolladores hablan el mismo idioma.
Errores comunes
Frequently Asked Questions
No. Los tokens representan decisiones de diseño, no cada valor CSS. Un ajuste puntual de 3px para alineación óptica no necesita un token. Concéntrate en valores reutilizados en múltiples componentes — colores, escala de espaciado, tamaños de fuente, sombras, radios y transiciones.
Sí. Configura tu tailwind.config.js para referenciar CSS custom properties: colors: { primary: "var(--color-primary)" }. Así las utilidades de Tailwind usan tus valores de tokens. Obtienes la conveniencia de clases utility con la consistencia basada en tokens.
Usa tipografía fluida con clamp(). Define tokens como --font-size-hero: clamp(2rem, 5vw, 3.5rem). La fuente escala suavemente entre el mínimo y máximo sin media queries. Cada componente que usa el token se beneficia automáticamente.
Aplica valores de tokens como overrides en el scope del componente de terceros. La mayoría de bibliotecas de componentes exponen CSS custom properties o theming basado en clases. Mapea tus tokens a su API de theming. Esto mantiene tu sistema visual consistente incluso con componentes externos.