Ratio de contraste WCAG: AA, AAA y APCA — La guía completa de 2026
Lanzas un botón. Naranja de marca, texto blanco, se ve nítido en tu monitor 4K. Después llega una auditoría de accesibilidad en rojo: el ratio de contraste WCAG es 1.97:1, lejísimos del umbral 4.5:1 AA para texto de cuerpo. Ese botón que a ti te parecía correcto es ilegible para unos 220 millones de personas con baja visión en todo el mundo. Esta guía recorre cada número que necesitas para arreglarlo: ratios WCAG 2, el nivel AAA, el nuevo algoritmo APCA Lc, ocho categorías de deficiencia de visión del color y una implementación funcional en JavaScript que puedes integrar directamente en tu build.
Referencia rápida: umbrales WCAG y APCA de un vistazo
| Estándar | Texto normal | Texto grande | UI / iconos | Notas |
|---|---|---|---|---|
| WCAG AA | ≥ 4.5:1 | ≥ 3:1 | ≥ 3:1 | Línea base legal |
| WCAG AAA | ≥ 7:1 | ≥ 4.5:1 | ≥ 3:1 | Objetivo reforzado |
| APCA body | Lc 75+ | Lc 60+ | Lc 45+ (iconos) | Borrador, perceptual |
“Texto grande” significa ≥ 18pt regular o ≥ 14pt bold (≈ 24px y ≈ 18.66px en CSS). “UI” cubre bordes de formulario, focus rings y cualquier objeto gráfico que el usuario tenga que percibir para operar la página. Los logos y los gráficos puramente decorativos quedan exentos de los requisitos de contraste.
¿Qué es el contraste de color WCAG?
El ratio de contraste WCAG es una medida numérica que va de 1:1 (sin contraste) a 21:1 (máximo) y compara la luminancia relativa del texto frente a su fondo. Las Pautas de Accesibilidad para el Contenido Web (WCAG) exigen ≥ 4.5:1 (AA) para texto de cuerpo o ≥ 7:1 (AAA) para un cumplimiento reforzado.
Ese ratio impulsa la mayoría de auditorías de accesibilidad del mundo. El W3C lo publicó en WCAG 2.0 en 2008, lo refinó en 2.1 (2018) y 2.2 (2023), y todo regulador relevante apunta hoy hacia él. La ADA en Estados Unidos, la Ley Europea de Accesibilidad (exigible desde junio de 2025), la Sección 508 para agencias federales estadounidenses y la AODA canadiense usan WCAG 2.x AA como su piso de facto.
¿Por qué importa esto más allá del ángulo legal? Unos 220 millones de personas en el mundo tienen baja visión sin ser ciegas: leen pantallas, pero solo cuando el contraste tipografía/fondo es lo bastante alto. Cerca del 8 % de los hombres y el 0.5 % de las mujeres presentan alguna deficiencia de visión del color. Los lectores mayores sufren amarillamiento del cristalino y una apertura pupilar reducida, lo que baja funcionalmente el contraste percibido entre un 20 y un 30 % después de los 60. Usar el smartphone al aire libre pierde otro 20-40 % por reflejos. Una página que en tu escritorio puntúa 4.5:1 es justo el piso desde el cual todas esas personas aún pueden leerla.
Quienes más necesitan tener esto presente son los ingenieros front-end que envían UI a producción, los diseñadores que eligen paletas de marca, los especialistas en accesibilidad que ejecutan auditorías y los equipos de compliance responsables de la exposición legal. La matemática es corta. Las decisiones que fuerza, no.
Ratio de contraste WCAG 2.x: la matemática, los umbrales
El W3C define el contraste en tres pasos breves. Para calcular el ratio de contraste WCAG: (1) convierte cada color de sRGB codificado en gamma a valores lineales de luz, (2) calcula la luminancia relativa usando coeficientes fijos para la sensibilidad del ojo humano al rojo, verde y azul, y (3) divide las dos luminancias con una pequeña constante de desplazamiento para manejar valores cercanos al negro.
La fórmula de luminancia relativa del WCAG 2.1 §1.4.3 es:
L = 0.2126 × R_lin + 0.7152 × G_lin + 0.0722 × B_lin
R_lin, G_lin, B_lin son los valores de canal en luz lineal tras deshacer la curva gamma sRGB. El peso 0.7152 sobre el verde refleja la fuerte sensibilidad del ojo humano al verde: este resulta unas 7× más “ruidoso” visualmente que el azul por unidad de energía luminosa.
La fórmula del ratio es:
ratio = (L_más_clara + 0.05) / (L_más_oscura + 0.05)
El +0.05 evita la división por cero para el negro puro (L = 0) y deja un máximo de (1 + 0.05) / (0 + 0.05) = 21:1 para blanco puro sobre negro puro. El mínimo es 1:1, colores idénticos.
Aquí tienes la implementación completa en unas treinta líneas de JavaScript vanilla. Cero dependencias, corre donde sea:
// sRGB hex → canal en luz lineal
function srgbToLinear(channel8bit) {
const v = channel8bit / 255;
return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
}
// "#RRGGBB" → luminancia relativa [0, 1]
function relativeLuminance(hex) {
const h = hex.replace("#", "");
const r = parseInt(h.slice(0, 2), 16);
const g = parseInt(h.slice(2, 4), 16);
const b = parseInt(h.slice(4, 6), 16);
return (
0.2126 * srgbToLinear(r) +
0.7152 * srgbToLinear(g) +
0.0722 * srgbToLinear(b)
);
}
// Ratio de contraste WCAG 2.x entre dos colores hex
function contrastRatio(hexA, hexB) {
const lA = relativeLuminance(hexA);
const lB = relativeLuminance(hexB);
const [lighter, darker] = lA > lB ? [lA, lB] : [lB, lA];
return (lighter + 0.05) / (darker + 0.05);
}
// Ejemplo: texto en slate oscuro sobre blanco
console.log(contrastRatio("#475569", "#ffffff").toFixed(2));
// → "7.58", cómodamente por encima de AA 4.5:1 y apenas sobre AAA 7:1
Pega dos códigos hex en el Convertidor de Color y obtendrás los mismos números, junto a un valor APCA Lc, una clasificación de gamut y una previsualización CVD de ocho canales. Los umbrales en sí son concretos:
| Elemento | AA mín | AAA mín | Notas |
|---|---|---|---|
| Texto de cuerpo normal | 4.5:1 | 7:1 | < 18pt regular / < 14pt bold |
| Texto grande | 3:1 | 4.5:1 | ≥ 18pt regular O ≥ 14pt bold |
| Componentes UI / iconos | 3:1 | — | WCAG 2.1 §1.4.11 añadido en 2018 |
| Logos y decorativos | exento | exento | Sin requisito de contraste |
Las conversiones de unidades CSS son la trampa habitual. 18pt = 24px en el valor por defecto del navegador, 14pt = 18.66px. Una fuente de cuerpo de 16px (el default moderno) queda por debajo del umbral de “texto grande”, así que cae bajo la regla más estricta de AA 4.5:1. Un encabezado de 20px en font-weight: 700 califica como grande y obtiene el 3:1 más holgado.
Un matiz que pilla a los equipos desprevenidos: la exención de “texto grande” de WCAG se basa en la legibilidad para el usuario a tamaño, no en la semántica del encabezado. Un <h2> a 14px no es texto grande: sigue necesitando 4.5:1. Un párrafo de copy de marketing a 24px sí es texto grande y obtiene el piso de 3:1. La regla se ancla al tamaño en píxeles renderizado y al peso, nunca al nombre de la etiqueta. Los auditores marcarán los desajustes; tu CSS es la fuente de verdad, no la semántica de tu HTML.
La constante +0.05 de la fórmula del ratio tiene un origen específico: representa el término de flare, la luz ambiente reflejada en la superficie de la pantalla que eleva la luminancia aparente del negro puro hasta un piso mínimo. Sin ella, un píxel OLED que renderiza negro real sobre blanco puro daría una división por cero. Con ella, el ratio máximo alcanzable es 21:1, un número que verás citado en toda herramienta de accesibilidad. No existe pantalla física capaz de entregar más de 21:1 una vez contabilizado el flare, por eso la escala WCAG se detiene allí.
AA vs AAA: ¿cuál deberías perseguir?
AA es el piso legal; AAA es el nivel aspiracional. La mayoría de sitios comerciales apuntan a AA porque AAA empuja los colores de marca hacia la escala de grises para lograr pasar, algo que casi ningún equipo de marketing está dispuesto a aceptar. La decisión no es “más es mejor”: es un balance entre alcance de usuarios y expresión de marca.
| Contexto | Nivel recomendado | Por qué |
|---|---|---|
| Sitio comercial general | AA | Línea base ADA / EAA; los tribunales citan WCAG 2 AA |
| Gobierno / servicios públicos | AAA | Sección 508 y estatutos UE equivalentes recomiendan AAA |
| Salud / educación | AAA | Base de usuarios con mayores necesidades de accesibilidad |
| Dashboard interno | AA | Audiencia conocida; trade-off de ROI aceptable |
| Landing de marketing | AA + reserva de marca | Colores de marca permitidos en hero/CTA, body sigue AA |
El coste oculto de AAA aparece la primera vez que intentas que un naranja saturado de marca pase 7:1 sobre blanco. No puede. O bien oscureces el naranja hasta que deja de ser tu marca, o aceptas AA y usas el naranja sobre fondos oscuros donde puede alcanzar AAA fácilmente. Muchas empresas (incluidas algunas de las más concienciadas con la accesibilidad) apuntan explícitamente a AA en contenido de cuerpo y solo empujan a AAA en texto crítico como mensajes de error o avisos legales.
Los reguladores no han esperado a que AAA se generalice. La regulación de accesibilidad web 2024 de la ADA cita WCAG 2.1 AA. La Ley Europea de Accesibilidad, exigible desde junio de 2025, requiere WCAG 2.1 AA en todos los servicios digitales cubiertos. La Sección 508 del gobierno federal estadounidense usa WCAG 2.0 AA como su línea base (con AAA recomendado donde sea factible). La AODA canadiense, el estatuto de accesibilidad de Ontario, apunta a WCAG 2.0 AA. El patrón se repite: AA es el listón, AAA es la meta.
APCA: el nuevo algoritmo perceptual
APCA (Advanced Perceptual Contrast Algorithm, diseñado por Andrew Somers bajo el sello Myndex) es un algoritmo candidato para WCAG 3. Reemplaza el ratio simétrico de WCAG 2 por un puntaje Lc con polaridad firmada de -108 a +108, donde el signo indica en qué dirección corre el contraste (texto oscuro sobre claro vs. texto claro sobre oscuro) y la magnitud refleja el contraste percibido en una pantalla emisiva real.
APCA importa porque la fórmula simétrica de WCAG 2 se pierde dos efectos del mundo real:
- Asimetría de polaridad. Texto claro sobre fondo oscuro se lee distinto que texto oscuro sobre fondo claro, incluso al mismo ratio WCAG. WCAG 2 devuelve el mismo número para ambas direcciones; APCA no.
- Modelado de pantalla. La fórmula de WCAG 2 derivaba de modelos de luminancia de papel impreso. APCA fue ajustada contra pantallas sRGB en iluminación de oficina típica, mucho más cerca de lo que tus usuarios ven realmente.
La contrapartida: APCA es más compleja (involucra exponentes sensibles a la polaridad y ajustes por peso de fuente) y todavía no es un estándar regulatorio. El análisis de abril de 2026 de Adrian Roselli sigue siendo el resumen más claro de dónde está APCA: es técnicamente prometedora, pero WCAG 3 sigue en desarrollo temprano vía Silver-track y APCA no se ha ratificado todavía como algoritmo oficial.
Los umbrales APCA de nivel Bronce (el piso práctico que la mayoría de equipos persigue) lucen así:
| Caso de uso | Lc recomendado | Lc mínimo |
|---|---|---|
| Texto de cuerpo (16px, peso 400) | 90+ | 75 |
| Texto grande (24px, peso 400) | 75+ | 60 |
| Elementos UI e iconos sin texto | 60+ | 45 |
| Spot text / placeholders | 30+ | 30 |
La razón por la que APCA es interesante (y por la que el Convertidor de Color muestra ambas métricas lado a lado) son los casos en que discrepa de WCAG 2:
#FFA500(naranja) sobre#FFFFFF: WCAG 2 devuelve 1.97:1, un fail claro en AA. APCA coincide, puntuando alrededor de Lc 38: también fail. Hasta aquí ambos algoritmos dicen que no, pero la mayoría de diseñadores que he observado siguen lanzando esta combinación porque “se ve bien”.#767676(gris medio) sobre#FFFFFF: WCAG 2 devuelve 4.54:1, apenas por encima de AA 4.5:1 y técnicamente un pass. APCA puntúa esta pareja en aproximadamente Lc 60, por debajo del umbral de 75 de APCA Bronce para texto de cuerpo. WCAG pasa; APCA suspende. La experiencia vivida del usuario está más cerca del veredicto de APCA: ese gris sobre blanco cuesta más leer en tamaños de cuerpo de lo que sugiere el ratio.#3b82f6(Tailwind blue-500) sobre#000000: WCAG 2 devuelve 5.71:1, un pass AA cómodo. APCA puntúa esto cerca de Lc 65, debajo del mínimo Lc 75 para texto de cuerpo. Texto azul claro sobre fondo oscuro, un patrón adorado del modo oscuro, es el caso canónico de “WCAG pasa, APCA marca”.
No tienes que tomar partido. La postura pragmática que la mayoría de equipos de producción ha adoptado: mantén WCAG 2 AA como línea base regulatoria porque es lo que las auditorías de cumplimiento revisan, y corre APCA en paralelo como gut check de “¿esto se lee realmente?”, sobre todo para diseños en modo oscuro y colores de marca saturados. El Convertidor de Color muestra ambos números en una sola fila para que no tengas que saltar entre checkers.
Daltonismo y más allá del contraste
Los ratios de contraste son solo la mitad de la accesibilidad cromática. Alrededor del 8 % de los hombres y el 0.5 % de las mujeres ven los colores de forma distinta al tricromata de manual, y la variante más común, la deuteranomalía, cae justo en el medio del par rojo/verde que usamos en todos lados para estados de éxito/error. La WCAG 1.4.1 (“Uso del color”) prohíbe explícitamente que el color sea el único portador de información; esta regla existe para forzar exactamente eso.
La taxonomía completa de diferencias de visión cromática se divide en tres grupos: dicromatismo (un cono ausente), tricromatismo anómalo (un cono desplazado) y las raras monocromatismos.
| Tipo | Nombre común | Canal afectado | Prevalencia (H / M) |
|---|---|---|---|
| Protanopia | Ciego al rojo | Cono L ausente | 1.0 % / 0.01 % |
| Deuteranopia | Ciego al verde | Cono M ausente | 1.1 % / 0.01 % |
| Tritanopia | Ciego al azul | Cono S ausente | 0.003 % / 0.003 % |
| Protanomalía | Débil al rojo | Cono L desplazado | 1.3 % / 0.02 % |
| Deuteranomalía | Débil al verde | Cono M desplazado | 5.0 % / 0.4 % |
| Tritanomalía | Débil al azul | Cono S desplazado | 0.01 % / 0.01 % |
| Acromatopsia | Sin color | Todos los conos ausentes | 0.003 % (muy raro) |
| Monocromatismo cono | Gris parcial | Un solo cono | 0.001 % |
La deuteranomalía por sí sola es el 5 % de los hombres: uno de cada veinte. Esa es la población que ve un indicador rojo de error y un indicador verde de éxito como casi el mismo tono oliváceo. La solución no es rediseñar tu sistema de color; es añadir un segundo canal. Un icono rojo de error junto a una forma de ”×” y la palabra “Error” sobrevive a todas las variantes de la tabla. Un simple punto rojo no.
Simular CVD en código usa dos conjuntos matriciales estándar: Brettel-Viénot-Mollon (1997) para los dicromatismos y Machado-Oliveira-Fernandes (2009) para los tricromatismos anómalos. El enfoque de Brettel proyecta el color de entrada del usuario sobre un plano definido por las dos respuestas de cono restantes; Machado parametriza el desplazamiento de cono según la severidad. Ambos se implementan como filtros SVG o matrices CSS. El Convertidor de Color trae las ocho variantes como previsualizaciones de un clic para que puedas escanear un color de marca a lo largo del espectro sin salir de la página.
Un filtro SVG breve (ponlo en tu página y referencia por ID) te da simulación de protanopia en navegador para pruebas ad hoc:
<svg style="display: none">
<filter id="protanopia">
<feColorMatrix type="matrix" values="
0.567 0.433 0.000 0 0
0.558 0.442 0.000 0 0
0.000 0.242 0.758 0 0
0.000 0.000 0.000 1 0"/>
</filter>
</svg>
<style>
.preview-protanopia { filter: url(#protanopia); }
</style>
Aplica .preview-protanopia al wrapper de tu página para ver lo que ve un protanope. Repite con las matrices de deuteranopia y tritanopia (sus coeficientes están documentados en el paper de Brettel y vienen empaquetados en la mayoría de librerías de simulación CVD). El panel Rendering de Chrome DevTools tiene los mismos simuladores integrados bajo “Emulate vision deficiencies”: útil para revisiones rápidas, menos útil para capturar screenshots en CI.
La regla central, más allá de la simulación: nunca dejes que el color sea la única diferencia entre dos estados. Los iconos deben diferir en forma (× vs ✓), los estados en etiqueta de texto (“Error” vs “Éxito”), las categorías en patrón (sólido vs rayado). El color es un multiplicador sobre esas otras señales, no un sustituto.
Hay una clase de fallos que los verificadores de contraste no detectan pero los simuladores CVD sí. Segmentos de gráfica circular distinguidos solo por matiz, leyendas de mapa que colorean países, pastillas de estado que dependen de un gradiente verde/amarillo/rojo: todos pueden pasar el contraste WCAG 2 contra el fondo y aun así ser ilegibles para un deuteranope que los lee entre sí. La regla es revisar la legibilidad entre colores adyacentes en el diseño, no solo contra el lienzo circundante. Dos segmentos slate-500 vecinos con la misma claridad son indistinguibles sin importar la rotación de matiz. Añade un paso de luminancia entre regiones adyacentes y la gráfica sobrevive a todas las variantes CVD.
La acromatopsia y el monocromatismo de cono son raros, pero vale la pena diseñar explícitamente para ellos porque colapsan todas las distinciones de matiz. Un usuario con acromatopsia percibe solo luminancia: tu UI codificada por color le parece una fotografía en escala de grises. Si tu diseño aguanta cuando aplicas filter: grayscale(1) sobre toda la página (pruébalo en DevTools), has pasado la versión más estricta de la regla “el color no es la única señal”. Es la prueba de accesibilidad más barata que puedes correr, y saca a la luz un número sorprendente de fallos en cuanto la activas.
Auditando paletas de Tailwind y Material
La mayor parte del trabajo front-end usa una paleta preconstruida: Tailwind v4, Material 3, Radix o shadcn. La pregunta de accesibilidad pasa a ser “¿en qué stop de esta rampa el texto se vuelve legible?”, y la respuesta es más regla empírica de lo que los docs admiten.
Para la rampa slate de Tailwind v4 contra blanco puro, los números WCAG y APCA caen así:
| Clase Tailwind | Hex aprox. | WCAG vs blanco | AA body | AAA body | APCA Lc (aprox.) |
|---|---|---|---|---|---|
| slate-400 | #94a3b8 | 2.56:1 | ✗ | ✗ | ~38 ✗ |
| slate-500 | #64748b | 4.76:1 | ✓ | ✗ | ~60 ✗ body |
| slate-600 | #475569 | 7.58:1 | ✓ | ✓ | ~78 ✓ body |
| slate-700 | #334155 | 10.35:1 | ✓ | ✓ | ~90 ✓ body |
Las reglas prácticas que se derivan:
- El texto de cuerpo necesita slate-600 o más oscuro. Slate-500 pasa WCAG AA pero falla el umbral APCA de texto de cuerpo, así que cumple pero es incómodo. Slate-600 es el piso seguro.
- Etiquetas UI y texto secundario pueden usar slate-500. Los componentes UI solo necesitan 3:1; los 4.76:1 de slate-500 son cómodos y el texto suele llevar contexto visual de apoyo.
- Los placeholders deberían usar slate-400 o aún más claro. El texto de placeholder está exento de WCAG 1.4.3 como decorativo solo si mantienes una etiqueta visible sobre el campo. Los patrones de “etiqueta inline como placeholder” deben alcanzar el umbral de texto de cuerpo.
- Negro puro sobre slate-100 / slate-200 es tinta desperdiciada. Estás a 17:1+; considera usar slate-700 o slate-800 como color de texto para un acabado más suave sin perder legibilidad.
Material 3 utiliza una estructura tonal similar. Su surface-container-high queda alrededor del tono 92 (muy claro); su on-surface queda alrededor del tono 10 (casi negro). El contraste entre cualquier on-surface y cualquier token surface-* de la misma familia está garantizado por la especificación de Material para superar AA. No emparejes on-surface-variant (tono 30) contra surface-container (tono 94) sin verificar: ese es un fallo real que he visto llegar a producción.
Si tienes una paleta existente que falla contraste, OKLCH te da el camino de corrección más limpio. En lugar de tocar códigos hex a ciegas, convierte tu color a OKLCH, mantén C (chroma) y H (hue) fijos y reduce L (lightness) hasta que el contraste pase. Como el canal L de OKLCH es genuinamente perceptual, el reconocimiento de marca queda intacto mientras el contraste se aprieta. La herramienta HEX a OKLCH hace esta conversión en un paso; el artículo hermano OKLCH explicado cubre la matemática en profundidad.
El modo oscuro merece su propio párrafo. El ratio simétrico de WCAG 2 pasa las mismas combinaciones en modo claro y oscuro por definición. APCA, al ser sensible a la polaridad, marca con frecuencia el texto de cuerpo en modo oscuro como más difícil de leer que el mismo par hex en modo claro. Claro-sobre-oscuro siempre pierde algo de contraste percibido respecto a oscuro-sobre-claro al mismo ratio numérico, un efecto conocido de cómo se adapta el ojo. Reejecuta APCA en cada par de modo oscuro antes de lanzar.
Verificadores de contraste y flujos CI
Diseñadores e ingenieros tienen cada uno su verificador favorito; la pregunta práctica es qué combinación de herramientas coses en un flujo real. Este es el panorama a 2026:
| Herramienta | WCAG 2 | APCA | Sim. CVD | Auditoría de paleta |
|---|---|---|---|---|
| WebAIM Contrast Checker | ✓ | ✗ | ✗ | ✗ |
| Adobe Color | ✓ | ✗ | ✓ | ✓ |
| Stark (plugin de Figma) | ✓ | ✓ | ✓ | ✓ |
| Polypane (navegador) | ✓ | ✓ | ✓ | ✓ |
| Color Picker de Chrome DevTools | ✓ | ✓ (exp.) | ✗ | ✗ |
| axe DevTools | ✓ | ✗ | ✗ | ✓ (a nivel de página) |
| Go Tools Color Converter | ✓ | ✓ | ✓ (8 tipos) | ✓ (Tints/Shades) |
Un flujo que aguanta la presión real de producto luce así:
- En Figma, los diseñadores corren Stark sobre cada frame para sacar a la luz pares fallidos cuanto antes. Stark atrapa a los infractores obvios antes de que ningún hex llegue al código.
- En el handoff de hex, los ingenieros pegan el valor en el Convertidor de Color para obtener ratio WCAG + APCA Lc + clasificación de gamut + preview CVD en una sola fila. Si el par es para modo oscuro o de marca saturada, la métrica dual atrapa los casos “WCAG pasa, APCA suspende” que Stark podría dejar pasar.
- En el PR,
axe-core/playwrightescanea las páginas construidas en busca de cualquier violación de contraste sobre el DOM renderizado, incluidos estados dinámicos. Esto atrapa focus rings, estados de hover y affordances disabled que los archivos de diseño estáticos pasan por alto. - En QA, la pestaña Rendering de Chrome DevTools simula protanopia/deuteranopia/tritanopia para revisiones puntuales en flujos críticos. El Color Picker de DevTools también muestra el ratio WCAG en línea cuando pasas el cursor sobre cualquier elemento.
Pa11y, Lighthouse CI y @axe-core/playwright exponen aserciones de contraste como parte de sus auditorías más amplias de accesibilidad. Ninguna revisa APCA hoy; todas revisan WCAG 2. El compromiso realista es “haz cumplir WCAG 2 AA en CI, comprueba APCA Lc manualmente como sanity check para colores de marca y modo oscuro”.
Un patrón que vale la pena tomar prestado de equipos grandes de sistemas de diseño: hornea la verificación de contraste en tu paso de validación de tokens, no solo en el QA a nivel de página. Si tus tokens de diseño compilan desde un archivo fuente (JSON, YAML o un módulo TypeScript), añade un script que enumere cada combinación --text-* × --surface-* permitida por el sistema y verifique un ratio WCAG mínimo. El script corre en milisegundos, atrapa regresiones cuando alguien toca el valor de un token y produce una matriz de contraste que sirve además como documentación para el equipo de diseño. La verificación es independiente de cualquier página renderizada: opera puramente sobre los tokens, así que atrapa el fallo antes de que ninguna UI se lance.
Para conversiones ad hoc durante este flujo (convertir entre hex, RGB, HSL y OKLCH mientras depuras), los spokes HEX a RGB, HEX a HSL, HEX a OKLCH y RGB a HEX cubren los viajes de ida y vuelta hacia y desde cualquier formato de color que tu toolchain espere.
Errores frecuentes y cómo corregirlos
Después de años de auditorías de accesibilidad, los mismos seis fallos aparecen una y otra vez. Cada uno tiene una corrección limpia:
-
Texto de placeholder en gris claro.
#999999sobre blanco da 2.85:1: falla AA. O profundiza a#666666(5.74:1, pasa AA), o —mejor— reemplaza los patrones de “placeholder como label” con una etiqueta visible permanente sobre el campo. Los placeholders no deberían cargar información. -
Botón naranja de marca con texto blanco.
#FFA500sobre blanco da 1.97:1: falla AA con holgura. La corrección que preserva la marca es invertir la dirección del contraste: texto oscuro (p. ej.#451a03) sobre fondo naranja, o mantén el texto blanco pero oscurece el botón a un naranja-marrón profundo y saturado. Verifica en el Convertidor de Color antes de lanzar. -
Enlace azul brillante en modo oscuro.
#3b82f6sobre#000000da 5.71:1 (pass WCAG AA), pero APCA Lc ~65, por debajo del umbral Lc 75 para cuerpo. Recurre a OKLCH y sube L de ≈ 0.63 a 0.75, manteniendo C y H fijos; aterrizarás cerca de#7aa5f8con un APCA Lc 80+ cómodo y el mismo matiz. -
Texto disabled en
#CCCCCC. 1.61:1 contra blanco. WCAG 1.4.3 exime el texto puramente decorativo de la regla del ratio, pero los controles UI deshabilitados no son decorativos: comunican “esto no está disponible ahora”. Empareja el color apagado con una pista no cromática (tachado, icono de candado, tooltip “Deshabilitado”) para que un usuario con CVD o baja visión siga entendiendo el estado. -
Iconos de estado que difieren solo en matiz. Un
×rojo y un✓verde está bien porque la forma ya los distingue. Un punto rojo vs un punto verde no. Usa forma y color juntos: la previsualización CVD del Convertidor de Color deja el caso de fallo evidente en un segundo. -
Texto sobre fondo en gradiente. Un gradiente que va de
#3b82f6a#a78bfacontra texto blanco pasa el contraste en el medio y falla cerca del extremo lavanda. La corrección es hacer cumplir el contraste contra el punto peor del gradiente, o superponer un scrim oscuro semitransparente para que la luminancia efectiva del fondo quede siempre bajo un umbral conocido.
Cada corrección lleva minutos. El ciclo de auditoría que evitan, semanas.
FAQ
¿Qué es el ratio de contraste WCAG AA?
WCAG AA exige ≥ 4.5:1 entre el texto de cuerpo y el fondo, o ≥ 3:1 para texto grande (≥ 18pt regular o ≥ 14pt bold) y componentes UI como bordes de formulario. AA es la línea base legal bajo ADA, EAA y Sección 508; la mayoría de sitios comerciales apuntan a AA porque cubre el listón regulatorio sin forzar a los colores de marca hacia la escala de grises.
¿Qué ratio de contraste necesito para AAA?
WCAG AAA exige ≥ 7:1 para texto de cuerpo normal y ≥ 4.5:1 para texto grande. AAA se recomienda para sitios médicos, educativos y gubernamentales donde la base de usuarios tiene mayores necesidades de accesibilidad. Los colores de marca suelen necesitar aplanarse hacia valores próximos a la escala de grises para pasar AAA, razón por la cual muchos productos comerciales se detienen en AA.
¿Qué es APCA y es WCAG 3.0?
APCA (Advanced Perceptual Contrast Algorithm), diseñado por Andrew Somers / Myndex, es un algoritmo candidato dentro del proyecto WCAG 3 Silver. Usa puntuaciones Lc sensibles a la polaridad de -108 a +108 en lugar de ratios simétricos. A fecha de 2026, WCAG 3 sigue en borrador temprano y APCA no ha sido ratificada formalmente: WCAG 2.1 / 2.2 AA sigue siendo el estándar regulatorio que debes cumplir hoy.
¿El modo oscuro ayuda a la accesibilidad del contraste?
A veces, pero no automáticamente. El ratio simétrico de WCAG 2 pasa las mismas combinaciones en modo claro y oscuro, pero APCA (que es sensible a la polaridad) suele marcar el texto de cuerpo en modo oscuro como más difícil de leer que el mismo par hex en modo claro. Reprueba siempre el modo oscuro contra ambos, WCAG y APCA, antes de lanzar; claro-sobre-oscuro pierde contraste percibido de formas que el ratio simétrico no puede ver.
¿Por qué mi color de marca falla WCAG AA?
Los colores saturados de luminancia media —la mayoría de naranjas, amarillos, verdes lima y azules claros— tienen valores de luminancia relativa demasiado cercanos al blanco para alcanzar 4.5:1. La corrección: conserva el matiz de marca para acentos y titulares grandes, pero empareja el texto de cuerpo con un tono más oscuro de la misma familia de matiz. Usa OKLCH para bajar el canal L sin desplazar el matiz: el Convertidor de Color encuentra el tono más cercano que pasa en un solo paso.
¿Son compatibles los ratios WCAG 2 y las puntuaciones APCA?
No. WCAG 2 devuelve un ratio simétrico (1-21); APCA devuelve una puntuación Lc con polaridad firmada (-108 a +108). La relación es no lineal: un par que es 4.5:1 en WCAG puede puntuar Lc 60 o Lc 75 en APCA según cuál color esté arriba. Trátalos como dos verificaciones independientes, no como traducciones la una de la otra.
¿Puedo aplicar contraste de color a iconos UI pequeños?
Sí, con matices. WCAG 2.1 §1.4.11 exige ≥ 3:1 para componentes UI y objetos gráficos. Para iconos decorativos acompañados de una etiqueta de texto visible, los requisitos de contraste se relajan: la etiqueta carga el significado. Para iconos autónomos (p. ej., una lupa de búsqueda sin etiqueta), haz cumplir los 3:1 completos contra el fondo circundante.
¿Cómo pruebo daltonismo sin simular?
Usa Chrome DevTools → Rendering → “Emulate vision deficiencies” para protanopia, deuteranopia, tritanopia y acromatopsia. Combínalo con la previsualización CVD de 8 tipos del Convertidor de Color para las variantes de tricromatismo anómalo (la deuteranomalía es la más común, con un 5 % de los hombres). Para el reporte de auditoría, captura screenshots bajo cada simulación para que los revisores vean los modos de fallo en línea.
Conclusión
Cinco ideas se llevan toda la guía:
- AA 4.5:1 es el piso legal. Acierta en todo el texto de cuerpo o espera ruido de compliance.
- AAA 7:1 es para salud, educación y gobierno. La mayoría de marcas comerciales se detienen en AA por diseño.
- APCA Lc es el sanity check de legibilidad real. Córrelo en paralelo con WCAG 2, sobre todo para modo oscuro y colores de marca saturados.
- El color nunca es la única señal. Empareja cada pista cromática con forma, texto o patrón; la deuteranomalía sola es el 5 % de los usuarios hombres.
- L de OKLCH es la perilla correcta. Cuando un color falla contraste, reduce L (no S, no B) para arreglarlo sin desviar el matiz.
Pega cualquier par de códigos hex en el Convertidor de Color para ver ratio WCAG, APCA Lc, clasificación de gamut y la previsualización CVD de 8 tipos lado a lado. Esa única vista reemplaza seis herramientas separadas y es la forma más rápida de cerrar las auditorías que describe esta guía.