Saltar al contenido

Accesibilidad

Contraste de texto

Cómo calcula WCAG 2.2 el contraste, qué piden los criterios 1.4.3 (AA) y 1.4.6 (AAA), por qué se comprueba cada par de tokens en cada modo y cómo cumple DesignToken101.

Última revisión:

El contraste entre un texto y su fondo es el criterio de accesibilidad que más depende de los tokens. En los módulos anteriores viste que el contraste decide a qué paso apunta cada semántico. En esta lección verás cómo se calcula, qué umbral pide cada nivel y cómo se comprueba un sistema entero, par a par.

En esta página

La fórmula

WCAG 2.2 calcula el contraste en dos pasos. La técnica G18 los describe (G18):

  1. La luminancia relativa de cada color (L): cuánta luz refleja, de 0 (negro) a 1 (blanco). Se calcula sobre los valores sRGB del color, convertidos a valores lineales: L = 0,2126 × R + 0,7152 × G + 0,0722 × B. El verde pesa mucho más que el azul porque el ojo es más sensible a él.
  2. La razón de contraste entre los dos colores: (L1 + 0,05) / (L2 + 0,05), donde L1 es la luminancia del color más claro y L2 la del más oscuro.

El resultado va de 1:1 (dos colores iguales) a 21:1 (negro sobre blanco).

Lo que dice la guía de 1.4.3 sobre cómo usarla (Understanding 1.4.3):

  • No se redondea. 4,499:1 no llega a 4,5:1.
  • Se mide con los colores que define el CSS, no con los píxeles que pinta la pantalla. El suavizado de los bordes de las letras no cuenta.

En Espacio de color viste la consecuencia para DesignToken101: el contraste se calcula sobre el hex guardado, que es el color que llega al CSS.

Los umbrales

CriterioNivelTexto normalTexto grande
1.4.3 Contrast (Minimum)AA4,5:13:1
1.4.6 Contrast (Enhanced)AAA7:14,5:1

Fuentes: Understanding 1.4.3 y Understanding 1.4.6.

El 4,5:1 no es arbitrario: compensa la pérdida de sensibilidad al contraste de una persona con una agudeza visual de 20/40, la habitual hacia los 80 años. El 7:1 está pensado para una agudeza de 20/80 (mismas fuentes).

Los dos criterios eximen el texto decorativo, el de componentes inactivos, el texto invisible, el que forma parte de una imagen con otro contenido importante y los logotipos. Por eso el logotipo de DesignToken101 queda fuera de la comprobación.

Un par, no un color

Un color no tiene contraste: lo tiene un par de colores. Por eso en DesignToken101 los primitivos no tienen una cifra de contraste propia. La tienen los pares de semánticos que se usan juntos: color/text/neutral/default sobre color/background/neutral/default, color/text/on-accent sobre color/background/accent/strong/default…

Y cada par se comprueba en cada modo. El mismo par de tokens tiene un hex distinto en Light y en Dark, así que tiene dos cifras. Un sistema con dos modos de color tiene el doble de comprobaciones que uno con un modo.

Cómo se comprueba un par

  1. Elegir el par, Token de texto y fondo donde se usa
  2. Leer el hex, El de cada modo, sin redondear
  3. Calcular la razón, Fórmula de WCAG 2.2
  4. Comparar con el umbral, 4,5:1 en el nivel AA
  5. Decidir, Vale, o se cambia un alias
Cómo se comprueba el contraste de un par de tokens, en cada modo.
  1. Elegir el par. El token de texto y cada fondo sobre el que aparece. Si un texto se usa sobre dos fondos, son dos pares.
  2. Leer el hex. El de la exportación de cada modo: es el hex que copiaste en el ejercicio del módulo 6.
  3. Calcular la razón con la fórmula de arriba, sin redondear.
  4. Comparar con el umbral del nivel que has elegido.
  5. Decidir. Si no llega, cambias el alias del texto o del fondo a otro paso de la escala, y vuelves a comprobar el par en los dos modos. Es lo que viste en El contraste decide el paso.

Texto grande

Para WCAG, texto grande es el de 18 puntos o más, o el de 14 puntos en negrita. En CSS equivale a unos 24 px, o unos 18,5 px en negrita (Understanding 1.4.3). Ese texto puede bajar a 3:1 en el nivel AA.

Recomendación

DesignToken101 no usa la excepción de texto grande: todos sus pares de texto llegan a 4,5:1. El motivo es de tokens. Un token de color no sabe a qué tamaño se va a usar, y en DesignToken101 los tamaños de los títulos cambian con el modo de Layout: heading/2 mide 32 px en Desktop y 24 px en Mobile (Crear los modos en Figma). Si un par de color dependiera del tamaño, habría que comprobarlo también en cada modo de Layout. Con 4,5:1 para todo, cualquier texto vale con cualquier color de texto.

Cómo cumple DesignToken101

tools/semantic.py calcula cada par de la especificación en Light y en Dark (comprobado el 2026-10-06). Todos los pares de texto llegan a 4,5:1, así que DesignToken101 cumple 1.4.3 (AA). Estos son los pares que no llegan a 7:1, el umbral de 1.4.6 (AAA), en algún modo, ordenados de menos a más margen en Light:

TextoFondoLightDark7:1 (AAA)
text/warning/defaultbackground/warning/subtle4,7710,32En Dark
text/success/defaultbackground/success/subtle4,8510,60En Dark
text/accent/defaultbackground/accent/subtle4,858,30En Dark
text/accent/defaultbackground/neutral/subtle4,869,83En Dark
text/accent/defaultbackground/neutral/default5,0810,92En Dark
text/danger/default (aún sin uso)background/danger/subtle5,758,49En Dark
text/on-accentbackground/accent/strong/active5,935,93No
text/info/defaultbackground/info/subtle5,998,10En Dark
text/accent/hoverbackground/neutral/hover6,6210,58En Dark
text/accent/hoverbackground/accent/subtle6,9010,60En Dark
text/neutral/subtlebackground/neutral/subtle7,406,89En Light

Los demás pares llegan a 7:1 en los dos modos. Entre ellos están el texto principal y el secundario sobre la página: text/neutral/default sobre background/neutral/default da 17,79 en Light y 18,89 en Dark, y text/neutral/subtle, 7,74 y 7,65. Los colores de acento y de mensaje en Light no llegan: sus pasos se eligieron para llegar a 4,5:1, que es el objetivo. Light es el modo que más se aleja de AAA.

Hay un par que no llega a 4,5:1: text/neutral/subtle sobre background/neutral/active en Dark, con 3,99:1. No se usa nunca, por una regla de Estados: en hover y active, el texto de los controles neutros pasa a text/neutral/default. Una regla de uso también es una forma de cumplir, si está escrita.

Fondos con transparencia

Un fondo translúcido no tiene un color propio: su color final depende de lo que pase por debajo. Por eso, en el ejercicio del módulo 6, anotaste el alpha de esos fondos.

Para comprobar un par sobre un fondo translúcido, calcula el peor caso: el fondo mezclado con el color más claro y con el más oscuro que puedan quedar debajo. En DesignToken101, la cabecera usa background/neutral/translucent (blanco al 96 % en Light, neutral/950 al 90 % en Dark). Lo que va encima es el logotipo, exento, el icono del botón de menú y el anillo de foco, que no son texto: lo verás en la lección siguiente, con el caso que llevó a subir Light al 96 %.

En Figma

Figma tiene un comprobador de contraste en el selector de color. Lo que dice su ayuda (Figma: Update fills using the color picker):

  • Se abre con Check color contrast, en el selector de color de la capa.
  • El color de la capa seleccionada es siempre el primer plano.
  • Muestra la razón de contraste, de 1:1 a 21:1, y si cumple los niveles AA o AAA de WCAG.
  • Puedes elegir el tipo de contenido: automático (según la capa seleccionada), texto grande, texto normal o gráficos. El nivel AAA está disponible para el texto, no para los gráficos. WCAG 2.2 tampoco tiene un criterio AAA para el contraste de lo que no es texto.

Recomendación

El comprobador de Figma te dice si cumple lo que ves en ese momento: un par, en el modo que tiene aplicado el marco. Úsalo mientras diseñas. Para comprobar el sistema, trabaja con la tabla de pares y el hex de cada modo: así ningún par ni ningún modo se queda sin revisar.

Lo que te llevas

  • El contraste es de un par de colores, y se comprueba con el hex de cada modo y sin redondear.
  • El nivel AA pide 4,5:1 para el texto normal; DesignToken101 lo exige a todo el texto porque un token no sabe a qué tamaño se usará.
  • El comprobador de Figma sirve para lo que ves; para el sistema, la tabla de pares.

Fuentes