Product Craft Bible
High contrast & forced-colors mode
Inicio Accesibilidad High contrast & forced-colors mode
Accesibilidad

High contrast & forced-colors mode

8 reglas MDN @media/forced-colors (Baseline sep 2022) · Microsoft Edge Blog "Styling for Windows High Contrast" (2020)MDN @media/forced-colors · Microsoft Edge Blog "Most web developers would need to write very few CSS rules"MDN CSS system-color (Canvas, CanvasText, ButtonFace, ButtonText, Highlight, LinkText, GrayText, AccentColor)MDN @media/forced-colors (box-shadow → none) · WCAG 1.4.11 Non-text Contrast (3:1) · Microsoft Edge Blog
22

High contrast & forced-colors mode

8 reglas
229

Trata forced-colors como una intervención del OS, no como un tema CSS

Cuando el usuario activa el modo de colores forzados (Windows High Contrast y equivalentes), el sistema operativo instruye al navegador a reemplazar la paleta de la página por un set limitado elegido por el usuario. No es un dark mode ni un tema: es una intervención a nivel OS que anula color, background-color, border-color, box-shadow, text-shadow y SVG fill/stroke. El objetivo del usuario puede ser legibilidad, menos ruido visual, mitigar migranas o sensibilidad a la luz, no necesariamente "más contraste" matematico. La respuesta correcta es dejar que el OS aplique su paleta y solo intervenir donde la conversión automática rompe la UX.

MDN @media/forced-colors (Baseline sep 2022) · Microsoft Edge Blog "Styling for Windows High Contrast" (2020)
Preferir
Tu paleta
Dejar que el OS sustituya
El sistema aplica la paleta elegida; tu solo ajustas lo que se rompe.
Evitar
Reescrito a mano
Asumir negro + blanco
Sobreescribir colores ignora la paleta real del usuario.
230

Usa @media (forced-colors: active) para ajustar, no para pelear contra el modo

La media query forced-colors: active es para retoques quirurgicos donde la conversión automática produce resultados deficientes, no para reimplementar todo el diseño. La plataforma ya garantiza la legibilidad base; el autor solo compensa los casos puntuales: un box-shadow perdido que deja un botón sin forma, o un gradiente eliminado que borra información de estado. Escribir un stylesheet paralelo completo para forced-colors es antipatron: duplica mantenimiento y puede contradecir las preferencias del usuario. Microsoft documenta que la mayoría de los sitios necesitan muy pocas reglas CSS para este modo.

MDN @media/forced-colors · Microsoft Edge Blog "Most web developers would need to write very few CSS rules"
Preferir
Compensar solo lo que se pierde
/* box-shadow quedo en none */ @media (forced-colors: active) { .button { border: 2px solid ButtonText; } }
Evitar
Redisenar todo el componente
@media (forced-colors: active) { .card { background: black; color: white; border: 1px solid white; } }
231

Usa system color keywords, no hex, para colores semánticos en forced-colors

Dentro de un bloque @media (forced-colors: active), los valores hex o RGB fijos pueden ser reemplazados de nuevo por el navegador, o no armonizar con la paleta del usuario. Los CSS system color keywords representan roles semánticos en la paleta del sistema y son la forma correcta de referirse a colores aquí: Canvas (fondo del documento), CanvasText (texto principal), ButtonFace/ButtonText (controles), Field/FieldText (inputs), Highlight/HighlightText (selección), LinkText, VisitedText, GrayText (deshabilitado), ButtonBorder, AccentColor/AccentColorText. Son 14 keywords vigentes que mapean a la paleta real.

MDN CSS system-color (Canvas, CanvasText, ButtonFace, ButtonText, Highlight, LinkText, GrayText, AccentColor)
Preferir
Canvas
CanvasText
ButtonFace
ButtonText
Highlight
LinkText
Evitar
background: #1a1a1a;
color: #ffffff;

Hex fijo dentro de forced-colors: el sistema lo ignora o lo reemplaza.
232

Los bordes definen la forma cuando el fondo desaparece

En forced-colors mode, background-color es reemplazado por la paleta del sistema y box-shadow es forzado a none. Un botón o card que dependa unicamente de su color de fondo para comunicar forma y límites quedara invisible o indiferenciable del Canvas. El border y el outline CSS siguen procesandose (con el color del sistema), lo que los vuelve los principales portadores de forma en este modo. La técnica es declarar siempre un borde, incluso transparente en modo normal: el OS le aplica su color y el elemento conserva forma. WCAG 1.4.11 exige 3:1 mínimo para la información visual que identifica controles.

MDN @media/forced-colors (box-shadow → none) · WCAG 1.4.11 Non-text Contrast (3:1) · Microsoft Edge Blog
Preferir
Guardar
border: 2px solid transparent → el OS lo colorea
Evitar
Guardar
Sin border: se funde con el Canvas
233

Los iconos SVG deben usar currentColor para heredar el color del sistema

En forced-colors mode, los atributos SVG fill y stroke con valores de color fijos son reemplazados por el sistema y pueden quedar ilegibles. currentColor es un valor CSS especial que hereda el color del elemento padre, y ese color si lo gestiona correctamente el modo forced-colors. Usar currentColor en iconos SVG evita colores incorrectos y elimina la necesidad de reglas específicas en @media (forced-colors: active): el icono se adapta automáticamente a light, dark y forced-colors con un solo valor. Coloca el SVG dentro de un elemento con color definido.

MDN @media/forced-colors (SVG fill/stroke afectados) · Microsoft Edge Blog "use currentColor in fills and strokes"
Preferir
currentColor
hereda color
Evitar
fill="#1a1a1a" fijo
234

No uses background-image para información esencial: desaparece en forced-colors

En forced-colors mode, los background-image que no son url() (gradientes, patrones CSS) son forzados a none, e incluso los url() pueden quedar invisibles si el Canvas cambia a un tono que los neutraliza. Cualquier información esencial que dependa exclusivamente de un background-image, marcas en checkboxes custom, iconos de estado, badges de color, progreso por gradiente, desaparece para usuarios de High Contrast. La solución es codificar el significado con elementos reales: un SVG inline o un ::before con content y un color del sistema, no un fondo decorativo.

MDN @media/forced-colors (background-image no-url → none) · Microsoft Edge Blog (text backplates, canales preservados salvo alpha)
Preferir
Check vía SVG inline + currentColor
Evitar
Check vía background: gradient
235

El foco debe ser visible en forced-colors sin depender de box-shadow

box-shadow es forzado a none en forced-colors mode, así que cualquier indicador de foco implementado solo con box-shadow, patrón común en design systems, desaparece justo para el grupo que más depende de un foco claro. La solución es declarar también un outline de color transparente en el estilo base: en modo normal se ve el box-shadow; en forced-colors el outline transparente recibe el color del sistema (tipicamente Highlight) y se vuelve visible automáticamente. WCAG 2.4.11 (Focus Appearance, AA en 2.2) exige área de al menos el perimetro x 2 CSS px y contraste 3:1.

MDN @media/forced-colors (box-shadow → none) · WCAG 2.4.11 Focus Appearance · Microsoft Edge Blog (transparent outlines)
Preferir
Continuar
outline transparente recibe Highlight
Evitar
Continuar
box-shadow forzado a none → foco invisible
236

prefers-contrast y forced-colors son distintos: responde a ambos por separado

prefers-contrast: more indica que el usuario prefiere mayor contraste sin necesariamente reemplazar colores: es una intención declarada dentro de tu paleta. forced-colors: active es una intervención real del OS que ya sustituyo los colores. El valor prefers-contrast: custom existe para el caso de paleta personalizada y se alinea con forced-colors: active. Responder solo a prefers-contrast: more no cubre a usuarios de High Contrast; responder solo a forced-colors no mejora la experiencia de quien quiere más contraste sin forzar colores. Cubrir ambos es valido y no son exclusivos.

MDN @media/prefers-contrast (Baseline may 2022; custom alinea con forced-colors) · MDN @media/forced-colors
Preferir
@media (prefers-contrast: more)
Refuerza bordes y texto dentro de tu paleta. No reemplaza colores.
@media (forced-colors: active)
Da forma con system color keywords; el OS ya tomo control de los colores.
Evitar
Solo prefers-contrast: more
Asume que cubre a todos. Los usuarios de High Contrast (paleta forzada por el OS) quedan sin atender porque su señal real es forced-colors.