Guía educativa de contrast-color()
Elegir texto para un fondo real
Deja que CSS elija entre blanco y negro para un color de fondo. Aprende a mantener el par sincronizado, reconocer los límites con transparencia e imágenes y comprobar el contraste de lo que se pinta.
Modelo mental
Un argumento de color, dos posibles resultados y una comprobación independiente.
- Color de referencia
El mismo token alimenta background-color y contrast-color().
- Elección del navegador
Devuelve blanco o negro; no inspecciona el contenido visual de la página.
- Comprobar el resultado
Mide el texto contra el fondo compuesto y revisa cada estado.
contrast-color(color) devuelve black o white. El algoritmo de elección lo define el navegador; no puedes pasarle una paleta de candidatos, un objetivo de ratio o el tamaño del texto. La función devuelve un color CSS que aquí usamos como primer plano.
Primer plano y fondo sincronizados
Una variable compartida evita elegir texto para otro color.
Define un color opaco de fondo y úsalo también en color: contrast-color(var(--button-color)). Si cambia esa variable, CSS vuelve a resolver ambos valores. No hace falta trasladar la elección de texto a un listener de JavaScript.
La misma regla sobre dos fondos opacos
Fondo #660066 · oscuro
Fallback activo: par de colores explícito; contrast-color() no se aplica.
Fondo #f5d0fe · claro
Fallback activo: par de colores explícito; contrast-color() no se aplica.
El primer fondo usa el estado por defecto y las declaraciones compartidas del lab. El segundo cambia solo el color. La guía permanece fuera del controlador: mover el selector del playground no modifica estas muestras.
Transparencia y composición
La misma entrada no describe dos fondos finales distintos.
Un color con alfa deja participar a las capas inferiores. contrast-color() recibe el color, no el fondo compuesto de la página. En estas muestras la entrada es siempre rgb(255 255 255 / 0.2), pero se pinta sobre dos bases diferentes. La función no recibe esa base como segundo argumento.
El mismo blanco al 20% sobre blanco y negro suave
Base #fff · blanco al 20%
Fallback activo: par de colores explícito; contrast-color() no se aplica.
Base #111 · blanco al 20%
Fallback activo: par de colores explícito; contrast-color() no se aplica.
Para texto de producción, usa una superficie opaca conocida o determina el color compuesto con todas sus capas y valida el par resultante. No calcules el contraste contra los canales RGB del color transparente aislado; cambiar la base, el tema o la opacidad del grupo exige revisar el resultado.
Imágenes, gradientes y límites
Un argumento no representa todos los píxeles de una imagen.
La función admite un valor de color, no una imagen ni un gradiente. Un color medio o tomado de una esquina no describe cada zona situada detrás del texto. Esta receta coloca una superficie opaca bajo el contenido y usa esa superficie como referencia.
Texto protegido de un fondo variable
Una superficie opaca define el fondo real de este texto.
Fallback activo: par de colores explícito; contrast-color() no se aplica.
Blanco o negro también limita la dirección visual: no devuelve un color de marca ni comprueba foco, bordes o iconos por ti. En fondos de tono medio, revisa tamaño, peso y legibilidad real aunque una medición alcance su umbral. Elige otra superficie si el texto resulta difícil de leer.
Comprobar el contraste
Separar la elección del navegador de la evaluación WCAG 2.2.
Para texto normal, WCAG 2.2 AA pide al menos 4.5:1; para texto grande, 3:1. La referencia de texto grande parte de 18 pt (24 CSS px) o 14 pt en negrita (aproximadamente 18.67 CSS px). Evalúa el tamaño efectivo y la fuente; ser un encabezado no basta.
| Fondo | Con negro | Con blanco |
|---|---|---|
#660066 | 1,76:1 Por debajo de 4.5:1 | 11,95:1 Alcanza 4.5:1 |
#f5d0fe | 15,34:1 Alcanza 4.5:1 | 1,37:1 Por debajo de 4.5:1 |
#777777 | 4,69:1 Alcanza 4.5:1 | 4,48:1 Por debajo de 4.5:1 |
Los ratios se calculan en servidor con luminancia relativa sRGB. Se muestran con dos decimales, pero el umbral se compara sin redondear. #777777 ilustra un resultado cercano al mínimo: no hay margen para ignorar transparencia, estados o cambios de superficie.
Ratio = (luminancia más clara + 0.05) / (luminancia más oscura + 0.05). Esta tabla solo calcula pares opacos #RRGGBB; no analiza píxeles, imágenes, alfa ni otros espacios de color.
- Obtén el color de texto computado y el fondo final detrás de él, incluidas las capas transparentes. Un background-color computado con alfa todavía necesita composición.
- Mide el par en una herramienta de contraste y repite la revisión con hover, foco, selección y cada tema. Con imágenes, revisa la zona menos favorable o protege el texto con una superficie conocida.
- Comprueba también teclado, foco visible, ampliación de texto y colores forzados. La información visual necesaria para identificar controles y estados tiene su propia exigencia de contraste; elegir el texto no resuelve toda la interfaz.
Una receta con fallback y estados
Conservar pares conocidos cuando falta la función.
El botón tiene pares de fondo y texto explícitos para reposo y hover/foco. @supports activa la elección nativa; sin ella, siguen aplicándose los pares revisados. El contorno de foco tiene su propio color y espacio, y los colores forzados conservan valores de sistema.
Un botón con dos estados de color
Fallback activo: par de colores explícito; contrast-color() no se aplica.
Si permites colores arbitrarios, los fallbacks fijos dejan de ser suficientes: limita la paleta, resuelve y verifica pares en servidor o añade una lógica que contemple el fondo real. var(--color, respaldo) no valida un token definido; protege funciones avanzadas con @supports y conserva valores válidos.
Errores frecuentes
Revisa primero la entrada, las capas y el par final.
Texto elegido para otro fondo
- Resultado esperado
- El argumento representa la superficie que hay detrás del texto.
- Causa
- El estado cambia background-color, pero la función conserva otro token.
- Solución
- Usa una variable compartida para ambas propiedades y revisa todos los estados.
El resultado falla sobre transparencia
- Resultado esperado
- Contraste suficiente contra el fondo compuesto.
- Causa
- La entrada transparente no incluye las capas inferiores ni la opacidad del grupo.
- Solución
- Fija una superficie opaca o calcula la composición real antes de validar el par.
Una parte del texto desaparece sobre la imagen
- Resultado esperado
- Lectura en toda la zona ocupada por el texto.
- Causa
- Un color de referencia no describe todas las zonas del gradiente o la fotografía.
- Solución
- Pon una superficie opaca detrás del texto o verifica la combinación más desfavorable.
Soporte confundido con accesibilidad
- Resultado esperado
- Contraste medido y contenido operable.
- Causa
- Se interpreta un @supports positivo como una auditoría de la interfaz.
- Solución
- Mide los colores finales y revisa tamaño, foco, teclado, estados y preferencias.
Soporte y compatibilidad
Compatibilidad de la función y validez del ejemplo son comprobaciones distintas.
En la consulta del 14 de octubre de 2026, MDN sitúa contrast-color() como Baseline Newly Available desde abril de 2026. BCD registra Chrome/Edge 147, Firefox 146 y Safari 26. Conserva fallback si tu público usa versiones anteriores.
La tarjeta Baseline consulta el estado del catálogo. @supports (color: contrast-color(#660066)) comprueba la sintaxis en el navegador actual; no comprueba tus tokens ni el contraste final. La especificación deja el algoritmo al navegador: una selección observada en un motor no certifica los demás.
Una sombra, un contorno de texto o un umbral de luminosidad aislado no garantizan contraste suficiente. Si usas otra estrategia de respaldo, comprueba el resultado sobre el fondo real con los mismos criterios.