Contraste: el ratio de WCAG 2, sus fallos y el cálculo de APCA
Cómo calcula el navegador el contraste, dónde verlo en el inspector, por qué la fórmula clásica falla con texto claro sobre fondo oscuro, y qué propone APCA.
El contraste es el único criterio de accesibilidad que se puede comprobar con una fórmula, y por eso es el que más herramientas automáticas tienen y el que más falsos veredictos produce. La fórmula de WCAG 2 tiene defectos conocidos y documentados: aprueba combinaciones ilegibles y suspende combinaciones perfectamente legibles, con un sesgo sistemático que afecta sobre todo a las interfaces oscuras. Saber dónde falla es lo que separa cumplir un número de hacer una interfaz legible.
- Leer el ratio de contraste en el selector de color y usar la línea de contraste.
- Explicar cómo se calcula el ratio de WCAG 2 y cuáles son sus umbrales.
- Enumerar los tres casos donde la fórmula clásica da un veredicto engañoso.
- Interpretar un valor de APCA y saber en qué se diferencia conceptualmente.
Dónde se lee en el inspector
Hay tres sitios y cada uno sirve para algo distinto.
En el selector de color, al abrir el cuadrito junto a una declaración de color en un elemento de texto. Muestra el ratio calculado contra el fondo y marca si cumple los umbrales. Además dibuja sobre el degradado la línea de contraste: una curva que separa los colores que cumplen de los que no. Arrastrar el selector hasta justo por encima de la línea da el color más parecido al que querías que sí cumple, lo cual es infinitamente más rápido que probar valores.
En el resaltado del inspector, la etiqueta flotante que aparece al pasar el cursor sobre un elemento de texto incluye el ratio. Es la vía para auditar rápido recorriendo una pantalla.
En la pestaña de problemas del cajón inferior, donde los avisos de contraste insuficiente aparecen agrupados con enlaces a los elementos afectados.
El cálculo del fondo que hace el navegador no es infalible. Cuando el texto está sobre una imagen, sobre un degradado, o sobre un fondo semitransparente con varias capas por debajo, las DevTools indican que no pueden determinar el color de fondo, o toman un punto que puede no ser representativo. En esos casos el número que ves no significa nada y la comprobación tiene que ser manual sobre las zonas de peor contraste.
Cómo se calcula el ratio de WCAG 2
Merece entenderse porque el mecanismo explica exactamente dónde falla.
Primero se calcula la luminancia relativa de cada color. Se toman los tres canales normalizados a cero-uno, se les aplica una corrección para deshacer la codificación gamma de sRGB, y se combinan con pesos fijos que aproximan la sensibilidad del ojo humano a cada primario: el verde pesa muchísimo, el rojo bastante menos, y el azul casi nada.
Después se combinan las dos luminancias en un cociente con una constante de compensación.
// El calculo exacto de WCAG 2, en 12 lineas
function canal(c) {
c /= 255;
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
}
function luminancia([r, g, b]) {
return 0.2126 * canal(r) + 0.7152 * canal(g) + 0.0722 * canal(b);
}
function ratio(a, b) {
const [l1, l2] = [luminancia(a), luminancia(b)].sort((x, y) => y - x);
return (l1 + 0.05) / (l2 + 0.05);
}
console.log(ratio([255, 255, 255], [0, 0, 0]).toFixed(2)); // 21.00
console.log(ratio([119, 119, 119], [255, 255, 255]).toFixed(2));
El resultado va de 1 —dos colores idénticos— a 21, que es blanco puro contra negro puro.
Los umbrales del nivel AA son 4.5 para texto normal, 3 para texto grande —definido como 24 píxeles o 18.66 en negrita— y 3 para componentes de interfaz y elementos gráficos necesarios para entender el contenido. El nivel AAA sube el de texto normal a 7 y el de texto grande a 4.5.
Los tres casos donde la fórmula engaña
El sesgo del modo oscuro. La constante de 0.05 del denominador tiene un efecto asimétrico: comprime las diferencias en la zona oscura de la escala. En la práctica, dos colores oscuros muy parecidos pueden alcanzar un ratio que cumple mientras son visualmente casi indistinguibles, y a la vez un texto gris claro sobre fondo negro puede suspender siendo perfectamente legible. Como las interfaces oscuras han pasado de excepción a norma, este sesgo dejó de ser académico.
La ceguera al peso y al tamaño de la fuente. La fórmula solo distingue dos categorías de tamaño, con un salto abrupto. Un texto de 23 píxeles necesita 4.5 y uno de 24 necesita 3, cuando la legibilidad varía de forma continua. Y no tiene en cuenta el grosor del trazo, que influye tanto o más que el tamaño: un texto fino de 30 píxeles es más difícil de leer que uno de peso medio de 16, y la fórmula dice lo contrario.
El ratio simétrico. El cociente es el mismo intercambiando texto y fondo, así que texto negro sobre gris medio y texto gris medio sobre negro dan el mismo número. Perceptualmente no son lo mismo en absoluto: la polaridad importa, y el texto oscuro sobre fondo claro se lee mejor a igualdad de ratio.
Qué propone APCA
El algoritmo de contraste perceptual, candidato para la siguiente generación de las pautas, ataca los tres problemas anteriores con tres decisiones de diseño.
Es asimétrico. Distingue texto oscuro sobre claro de texto claro sobre oscuro y da valores distintos, con signo: positivo para un caso y negativo para el otro. El valor se llama contraste de luminosidad, abreviado Lc, y su escala va aproximadamente de menos ciento ocho a ciento seis.
Incorpora el tamaño y el peso. No hay un umbral único: hay una tabla que cruza el valor Lc con el tamaño en píxeles y el peso de la fuente, de forma que un texto grande y grueso necesita menos contraste que uno pequeño y fino. Como orientación general, alrededor de 60 se considera el mínimo para texto de cuerpo, y alrededor de 75 para texto pequeño o de lectura sostenida; por debajo de 30 el uso queda restringido a elementos no textuales.
Usa un modelo perceptual distinto, con exponentes que aproximan mejor la respuesta del sistema visual en condiciones de pantalla, en lugar de la fórmula de luminancia relativa heredada de las especificaciones de los años noventa.
En las DevTools, el cálculo de APCA aparece cuando está disponible en la versión que tengas, normalmente detrás de un experimento o del ajuste de umbral avanzado. Cuando está activo, el selector de color muestra el valor Lc en lugar del ratio, y la línea de contraste se recalcula con el nuevo criterio.
La consecuencia práctica de todo lo anterior es incómoda de aceptar para cualquiera que trabaje con requisitos de cumplimiento: el número no es el objetivo. Hay combinaciones que dan 4.51 y son un castigo para la vista, y hay combinaciones que dan 4.3 y se leen sin ningún esfuerzo. La fórmula de WCAG 2 es un umbral legal y un instrumento de medida imperfecto, y confundir ambas cosas produce dos errores opuestos y ambos caros. El primero es diseñar hasta justo por encima del umbral: un texto a 4.5 exactos no tiene ningún margen, y basta con que el usuario tenga el brillo bajo, esté al sol, use un panel barato o tenga cincuenta años para que deje de ser legible. La cifra es un mínimo absoluto, no un objetivo de diseño, y apuntar a 7 en el texto de cuerpo cuesta poco y cambia mucho. El segundo error es el contrario y es más sutil: rechazar una decisión de diseño buena porque un validador automático la marca, cuando la combinación cae en uno de los casos donde la fórmula falla. El ejemplo típico es el texto gris claro sobre fondo casi negro en una interfaz oscura, que suspende WCAG 2 con frecuencia y que APCA aprueba, y que cualquiera que lo mire confirma que se lee bien. Lo que hay que hacer en ese caso no es ignorar el aviso ni obedecerlo ciegamente: es mirarlo con la simulación de deficiencias de visión activada y con el brillo de la pantalla bajado, y decidir con los ojos. La herramienta correcta para tomar esa decisión no es un número, es la comparación entre lo que dicen los dos algoritmos y lo que ves. Cuando ambos coinciden, hazles caso. Cuando discrepan, ahí es donde hace falta el criterio, y donde entender por qué discrepan te da la respuesta.