Saltar al contenido

Primitivos

Espacio de color

Por qué DesignToken101 construye sus escalas de color en oklch y las guarda en sRGB, qué pasa con los colores fuera de gama, qué límites tiene Figma y cómo reproducir las conversiones con el script del repositorio.

Última revisión:

Los colores de DesignToken101 no se eligieron uno a uno en el selector de Figma. Se generaron a partir de un único color de marca, con un método que trabaja en un espacio de color (oklch) y guarda el resultado en otro (sRGB). En esta lección verás cómo se hizo, qué significa cada espacio, por qué los separamos, qué límites tiene Figma y cómo reproducir las conversiones con el script del repositorio.

En esta página

Cómo se crearon los colores de DesignToken101

  1. Elegir el color de marca, Un único color: #33CC99
  2. Generar las escalas, Script, en oklch: 11 pasos por escala
  3. Ajustar a sRGB, El script reduce el croma si no cabe
  4. Copiar los hex a Figma, Variables de la colección Primitives
  5. Diseñar con tokens semánticos, Alias de esos primitivos
  6. Exportar y generar el CSS, El mismo hex, sin conversión
Cómo se crearon los colores de DesignToken101, desde el color de marca hasta el CSS.
  1. Elegir el color de marca. Es la decisión de partida: #33CC99, en HSL 160°, 60 %, 50 %. Las demás decisiones estéticas (cuánto tinte llevan los grises, cuánto croma las escalas de estado) son parámetros del método.
  2. Generar las escalas. El script tools/scales.py convierte el color de marca a oklch y calcula once pasos para el acento, once para los neutros y once para cada color de estado. Cómo calcula cada paso lo verás en Escalas de color.
  3. Ajustar a sRGB. Si algún paso calculado no existe en sRGB, el script lo convierte en el más parecido que sí existe. Da como resultado un hex por paso.
  4. Copiar los hex a Figma. Cada hex se escribe en una variable Color de la colección Primitives: color/emerald/500 = #33CC99. Figma no genera escalas; recibe los valores ya calculados.
  5. Diseñar con tokens semánticos. Al diseñar, nadie aplica un hex ni un primitivo: se aplican tokens semánticos como color/text/neutral/default, que apuntan a los primitivos. Los verás en el módulo Relaciones.
  6. Exportar y generar el CSS. La exportación de Figma lleva los mismos hex al código, sin conversiones. Lo verás en el módulo De Figma al código.

Y el contraste. El contraste no se usó para generar las escalas. Se calcula después, sobre cada hex, para saber qué pasos sirven para texto, para bordes o para fondos. Con esas cifras se decide a qué paso apunta cada token semántico: por ejemplo, que el texto de los enlaces en Light use emerald/700 y no el color de marca, que no llega a 4,5:1 sobre blanco.

Nota

Si no quieres usar un script, puedes hacer los pasos 2 y 3 con un selector de color que trabaje en oklch y muestre los límites de sRGB, como oklch.com, de Evil Martians. Es más lento y menos exacto, pero el método es el mismo.

Los apartados siguientes explican por qué el proceso es así.

Espacio de color y gama

Un espacio de color es una forma organizada de describir colores con coordenadas, normalmente tres. Cada espacio tiene una gama: el conjunto de colores que puede representar (MDN: Color space).

Tres espacios aparecen en este curso:

EspacioQué esCoordenadas
sRGBEl espacio estándar de la web y el más compatible. Su gama es más estrecha que la de Display P3Rojo, verde y azul, de 0 a 1 (o un hex como #33CC99)
Display P3Un espacio de gama más ancha, típico de las pantallas de gama ancha actuales: verdes y rojos más intensos que sRGBRojo, verde y azul, de 0 a 1
oklchUna forma de describir el color según cómo lo percibimos, basada en OklabLuminosidad (L), croma (C) y tono (H)

Las dos primeras definiciones son de MDN (misma fuente). Oklab es un modelo publicado por Björn Ottosson en 2020 para que los cambios de luminosidad, croma y tono se perciban como independientes entre sí (Ottosson: A perceptual color space for image processing). oklch es su forma polar.

Nota

oklch no tiene una gama propia limitada como sRGB: su croma no tiene un máximo teórico, aunque en la práctica no supera 0,5 (MDN: oklch()). Por eso con oklch puedes escribir colores que ninguna pantalla sRGB puede mostrar.

Para entender mejor oklch. Es un concepto difícil de captar solo leyendo. Estos recursos lo muestran de forma visual:

  • Vídeo: Thinking on ways to solve color palettes, de Adam Argyle (Chrome for Developers, 2023, unos 24 minutos, en inglés). Compara HSL con LCH y construye paletas en oklch.
  • Herramienta: oklch.com, de Evil Martians. Mueve L, C y H y verás dónde termina la gama sRGB.
  • Artículo: OKLCH, explained for designers, de Samuel Wong (UX Collective, 2025, en inglés). Es un blog, no documentación oficial.

Por qué construir en oklch

En oklch, L representa la luminosidad tal como la percibimos (MDN: oklch()). En HSL, uno de los modelos del selector de color de Figma, la luminosidad es una cuenta sobre los canales RGB, no una medida de lo que vemos.

Un ejemplo lo muestra. No es una prueba para elegir colores, sino una comparación calculada con el script: tres colores con la misma luminosidad en HSL, 50 %.

Color en HSLHexL en oklchContraste con blanco
hsl(60 100% 50%), amarillo#FFFF000,9681,07:1
hsl(120 100% 50%), verde#00FF000,8661,37:1
hsl(240 100% 50%), azul#0000FF0,4528,59:1

Para HSL los tres son "igual de claros". A la vista, y para el contraste, no se parecen en nada. oklch sí refleja la diferencia.

Para una escala, eso importa por dos motivos:

  • Pasos regulares. Si fijas la L de cada paso, el salto visual entre dos pasos es parecido en cualquier tono.
  • Claridad comparable. Dos pasos con L muy distinta se ven muy distintos en claridad. El contraste de WCAG, en cambio, se calcula con otra fórmula, así que la cifra hay que calcularla siempre (lo verás abajo).

Recomendación

DesignToken101 construye las escalas en oklch: decide la L y el croma de cada paso y mantiene el tono. Es lo mismo que hace Tailwind CSS, cuya paleta por defecto se define en oklch desde la versión 4 (Tailwind CSS: Colors).

Por qué guardar en sRGB

Lo que dicen las fuentes:

  • La importación de variables en formato DTCG de Figma admite color en sRGB y HSL (Figma: Modes for variables).
  • Los archivos nuevos de Figma usan el perfil de color sRGB. Se puede cambiar a Display P3 en cualquier plan; al convertir el perfil, los valores de las variables de color no cambian (Figma: Manage color profiles).
  • El Color Module de DTCG admite catorce espacios de color, entre ellos srgb, display-p3 y oklch, y un hex opcional de reserva (Color Module 2025.10).
  • Al exportar las variables de esta web, Figma escribe cada color con "colorSpace": "srgb" y su hex (comprobado en la exportación).

Recomendación

DesignToken101 guarda los colores en sRGB. Los valores sRGB son la fuente de verdad en Figma, el archivo trabaja con el perfil sRGB y el CSS escribe el mismo valor en hexadecimal, sin conversiones. Así, el color que ves en Figma es el que se exporta y el que llega a la web.

Por qué no Display P3. Daría verdes más intensos en las pantallas que lo admiten. Lo descartamos porque la importación DTCG de Figma no lo admite y porque añade una capa de complejidad al curso. Es una decisión nuestra; no es una norma.

Colores fuera de gama

Construir en oklch y guardar en sRGB tiene una consecuencia: algunas combinaciones de L, C y H no caben en sRGB. Hay que llevarlas a un color que sí quepa.

La propia paleta de Tailwind CSS lo muestra. Desde la versión 4 aprovecha la gama más ancha de las pantallas modernas para que los colores sean más intensos (Tailwind CSS v4.0). Con el script del repositorio comprobamos que green-500, green-600 y green-700 de Tailwind quedan fuera de sRGB: green-500 tiene un croma de 0,219, y en sRGB su máximo con esa L y ese tono es 0,201.

El método de DesignToken101 para llevar un color a sRGB:

  • Se conservan L y H. El color sigue siendo igual de claro y del mismo tono.
  • Se reduce el croma hasta que el color cabe.

El módulo CSS Color 4 del W3C sigue la misma idea: su algoritmo de mapeo de gama trabaja en OKLCh y reduce el croma (CSS Color 4: Gamut mapping). Es un borrador de recomendación candidata, no una recomendación final.

Nota

En las escalas de DesignToken101 el ajuste no llega a actuar: al multiplicar el croma de Tailwind por 0,66 (lo verás en Escalas de color), todos los pasos caben en sRGB. El ajuste está en el método para que funcione con cualquier color de marca.

Los límites de Figma

  • El selector de color acepta oklch. El modelo de color CSS del selector admite oklch(), oklab() y color(display-p3 …), y Figma guarda el valor en el espacio de color en el que lo escribiste, sin convertirlo (Figma: Color models).
  • La importación DTCG no acepta oklch. Admite sRGB y HSL (Figma: Modes for variables).
  • Figma no genera escalas. Puedes escribir un color, pero el método (L por paso, croma, ajuste de gama) lo tienes que aplicar tú o un script.

Recomendación

En DesignToken101 escribimos en Figma el hex en sRGB que da el script, no el valor en oklch. Es el espacio que admite la importación DTCG de Figma y el del perfil de color del archivo, así que lo que guarda Figma es lo que llega al CSS.

El contraste se mide sobre lo que se guarda

WCAG 2.2 calcula el contraste a partir de la luminancia relativa de cada color en sRGB, y pide no redondear: 4,499:1 no cumple el mínimo de 4,5:1 (Understanding 1.4.3).

Recomendación

En DesignToken101 el contraste se calcula siempre sobre el hex guardado, no sobre la L de oklch ni sobre el valor antes de redondear al hex. La L sirve para construir la escala; la cifra que vale para accesibilidad es la de WCAG sobre el color final.

En Figma

  1. Comprueba que el archivo usa el perfil de color sRGB (Figma: Manage color profiles). Es el valor por defecto.
  2. Al crear una variable Color, escribe su valor en hex, el que da el script. No hace falta cambiar el modelo de color del selector.

Las variables de color las crearás en Escalas de color.

Lo que te llevas

  • Las escalas se construyen en oklch, porque su L representa la luminosidad tal como la percibimos.
  • Los colores se guardan en sRGB, que es lo que Figma importa y exporta sin conversiones.
  • El contraste se mide sobre el hex guardado, no sobre los valores con los que se calculó.

Fuentes