Lección 4 de 10 · 14 min de lectura · Revisado el 26/10/2026
Preferencias del usuario en CSS: colores forzados, contraste y modo oscuro
Cada vez más personas ajustan su sistema operativo para ver mejor: un tema de contraste en Windows, el modo oscuro en el móvil, «aumentar contraste» en macOS, un tamaño de letra mayor en el navegador. El navegador traslada esas preferencias a la web, y el CSS puede respetarlas o pisarlas. En el curso de color y contraste viste estos modos desde el diseño; esta lección te da el código para que la interfaz se adapte sin perder información, con especial atención al modo de colores forzados, el que más webs rompe. El movimiento reducido tiene lección propia, la siguiente.
Las preferencias que el sistema expone a la web
Las preferencias se consultan con media features (características de medio) dentro de @media, igual que el ancho de pantalla:
| Característica | Valores | Qué la activa | Qué debe hacer tu CSS |
|---|---|---|---|
forced-colors | none, active | Temas de contraste de Windows (soportado en navegadores Chromium y Firefox) | Dejar que el sistema pinte y asegurar bordes, foco e iconos |
prefers-contrast | no-preference, more, less, custom | «Aumentar contraste» en macOS e iOS, entre otros ajustes | Reforzar bordes, quitar transparencias y grises tenues |
prefers-color-scheme | light, dark | Modo claro u oscuro del sistema | Ofrecer un tema oscuro que cumpla el mismo contraste |
prefers-reduced-motion | no-preference, reduce | «Reducir movimiento» | Quitar el movimiento espacial (lección siguiente) |
A ellas se suma una preferencia que no es una media query: el tamaño de letra por defecto del navegador, que solo se respeta si usas rem y em, como vimos en la primera lección.
Infografía · Conceptos clave
Seis preferencias del usuario que tu CSS debe respetar
Cada ajuste del sistema llega a la web como una media query, una propiedad o una unidad
- forced-colorsTemas de contraste: bordes y contornos transparentes, colores del sistema
- prefers-contrastCon «more», refuerza bordes y quita grises tenues y transparencias
- prefers-color-schemeTema oscuro con el mismo contraste que el claro: 4,5:1 y 3:1
- color-schemeAdapta controles nativos y barras de desplazamiento al tema
- prefers-reduced-motionSustituye el movimiento espacial por fundidos o elimínalo
- Tamaño de letra baseSolo se respeta con rem y em, no con fuentes en píxeles
Leer la infografía como texto
Seis tarjetas, cada una con una preferencia y lo que debe hacer el CSS. forced-colors: con los temas de contraste de Windows, usa bordes y contornos transparentes y colores del sistema. prefers-contrast: con el valor more, refuerza bordes y elimina grises tenues y transparencias. prefers-color-scheme: el tema oscuro debe cumplir el mismo contraste que el claro, 4,5:1 para texto y 3:1 para componentes. color-scheme: esta propiedad adapta los controles nativos y las barras de desplazamiento al tema. prefers-reduced-motion: sustituye el movimiento espacial por fundidos o elimínalo. Tamaño de letra base del navegador: solo se respeta con unidades rem y em, no con fuentes en píxeles.
El modo de colores forzados a fondo
Cuando una persona activa un tema de contraste en Windows (por ejemplo, fondo negro con texto amarillo, o el tema «Desierto» de fondo claro), el navegador sustituye los colores de la página por una paleta reducida que ella ha elegido. Lo usan personas con baja visión, con fotofobia, con migraña o con dificultades de lectura. Lo que ocurre con tu CSS:
- Los colores de texto, fondo, bordes y contornos se sustituyen por los del sistema. Tus colores de marca desaparecen; es lo que la persona ha pedido.
box-shadowytext-shadowse eliminan.- Los degradados de fondo desaparecen; las imágenes con
url()se mantienen, y el navegador pinta un fondo opaco detrás del texto para que siga siendo legible. - Los controles nativos (
button,input,select) se redibujan con los colores del sistema y siguen siendo reconocibles.
Los problemas aparecen cuando la interfaz transmite forma, estado o información solo con colores de fondo o sombras: un botón que es «un rectángulo azul» sin borde se convierte en texto suelto; una casilla de verificación personalizada hecha con un div coloreado pierde su marca; una barra de progreso o un indicador de estado verde o rojo desaparecen; el foco hecho con box-shadow se esfuma.
Ejemplo
El truco de los bordes transparentes: invisibles en modo normal, el sistema los pinta en modo forzado.
.boton {
background: #0b5394;
color: #ffffff;
border: 2px solid transparent; /* aparece con colores forzados */
}
.boton:focus-visible {
outline: 3px solid transparent; /* idem para el foco */
box-shadow: 0 0 0 3px #ffbf47; /* lo que se ve en modo normal */
}
.icono { fill: currentColor; } /* el icono hereda el color del texto */
@media (forced-colors: active) {
.tarjeta-seleccionada { border: 3px solid Highlight; }
.estado-activo { border-left: 4px solid CanvasText; } /* marca que no depende del fondo */
.muestra-color { forced-color-adjust: none; } /* aquí el color es el contenido */
}Dentro de forced-colors: active no uses colores concretos, que el sistema volvería a sustituir, sino colores del sistema: palabras clave de CSS que toman el valor del tema activo. Las más útiles son Canvas y CanvasText (fondo y texto), LinkText (enlaces), ButtonFace, ButtonText y ButtonBorder (botones), Highlight y HighlightText (selección y elementos activos) y GrayText (deshabilitado). Así, un estado «seleccionado» puede marcarse con un borde Highlight grueso en lugar de con un fondo de color.
Los iconos SVG con colores fijos en el atributo fill pueden quedar invisibles sobre el fondo del sistema (un icono negro sobre fondo negro). Con fill: currentColor heredan el color del texto y se adaptan solos. Las imágenes de mapa de bits no se tocan: un logotipo con texto oscuro sobre transparencia puede desaparecer sobre un tema oscuro, igual que en el modo oscuro que verás más abajo.
Error frecuente
Aplicar forced-color-adjust: none a toda la web «para conservar la imagen de marca». Anula precisamente la adaptación que la persona necesita y suele dejar textos ilegibles. Esa propiedad está pensada para casos puntuales en los que el color es el contenido (muestras de color de un producto, un selector de color) y, aun entonces, el texto que acompaña debe seguir siendo legible. Tampoco uses la antigua media query -ms-high-contrast: está obsoleta y los navegadores actuales la ignoran.
prefers-contrast: más contraste cuando se pide
prefers-contrast: more se activa cuando la persona pide más contraste sin llegar a forzar los colores. No sirve para cumplir 1.4.3 Contraste (mínimo): la versión por defecto ya debe cumplirlo. Es una mejora para quien necesita aún más:
@media (prefers-contrast: more) {
:root { --texto-secundario: #1a1a1a; --borde: #000000; }
.campo { border-width: 2px; }
.cabecera { background: #ffffff; backdrop-filter: none; } /* fuera transparencias */
.placeholder-sutil::placeholder { color: #333333; }
}
Buenos candidatos para reforzar: textos grises secundarios, bordes finos de campos y tarjetas, fondos semitransparentes o con desenfoque, texto sobre fotografías y separadores tenues.
Modo oscuro sin romper la accesibilidad
Un tema oscuro bien hecho empieza por organizar los colores en variables (los tokens de diseño) y redefinirlas, no por reescribir cada regla:
:root {
color-scheme: light dark; /* controles nativos y barras de desplazamiento se adaptan */
--fondo: #ffffff; --texto: #1a1a1a; --enlace: #0b5394; --foco: #1a1a1a;
}
@media (prefers-color-scheme: dark) {
:root { --fondo: #121212; --texto: #e8e8e8; --enlace: #8ab4f8; --foco: #ffffff; }
}
body { background: var(--fondo); color: var(--texto); }
a { color: var(--enlace); }
Si el tema oscuro se aplica automáticamente según la preferencia del sistema, para esa persona es la página: debe cumplir 1.4.3, 1.4.11 Contraste no textual y 1.4.1 Uso del color igual que el tema claro. Mide el contraste en los dos temas, incluidos el indicador de foco, los bordes de los campos y los mensajes de error, y revisa estos fallos típicos:
- Logotipos e imágenes PNG con partes oscuras sobre transparencia que desaparecen sobre fondo oscuro. Solución: una versión clara con
<picture>y<source media="(prefers-color-scheme: dark)">, o un fondo propio en la imagen. - Sombras como única separación entre tarjetas: sobre fondo oscuro no se ven; usa bordes o cambios de luminosidad.
- Colores de marca muy saturados que sobre negro vibran o no contrastan; necesitan una variante más clara.
- Gráficos y mapas con colores pensados para fondo blanco.
Si ofreces un selector de tema propio, respeta por defecto la preferencia del sistema, guarda la elección en localStorage, aplícala antes de pintar la página (para evitar el destello del tema contrario) y haz el selector accesible: un grupo de botones de opción «Claro, Oscuro, Según el sistema» o un botón con aria-pressed. La función light-dark(), más reciente, permite escribir los dos valores en una sola declaración; compruébala en los navegadores que debas soportar antes de depender de ella.
Cómo comprobarlo
- En Chrome y Edge, abre las herramientas de desarrollo, menú «More tools», panel «Rendering»: permite emular
prefers-color-scheme,prefers-contrast,forced-colorsyprefers-reduced-motionsin cambiar el sistema. - La emulación no sustituye a la prueba real: en Windows, activa un tema de contraste (Configuración, Accesibilidad, Temas de contraste) y recorre la web con el teclado.
- Busca en el CSS
box-shadowusados como foco o borde,backgroundque transmite estado yfillcon colores fijos en los SVG. - Mide el contraste del tema oscuro con el mismo rigor que el del claro.
Pruébalo tú
En un ordenador con Windows, pulsa Alt izquierda + Mayús izquierda + Impr Pant para activar o desactivar el contraste alto (Windows pedirá confirmación). Abre la web de tu organización y localiza tres cosas: un botón que haya perdido su forma, un icono que haya desaparecido y un control cuyo foco ya no se vea. Vuelve a pulsar la combinación para salir.
Punto clave
Las preferencias del sistema son decisiones de la persona, no caprichos que la marca deba corregir. Diseña para que la forma, el estado y el foco no dependan solo del color de fondo ni de las sombras: bordes y contornos transparentes, currentColor en los iconos, colores del sistema en modo forzado y el mismo contraste en el tema oscuro que en el claro.
Resumen
forced-colors,prefers-contrastyprefers-color-schemeexponen preferencias del sistema; el tamaño de letra se respeta conrem.- En colores forzados desaparecen las sombras y los degradados: usa bordes y contornos transparentes,
fill: currentColory colores del sistema comoHighlightoCanvasText. - Reserva
forced-color-adjust: nonepara cuando el color es el contenido. prefers-contrast: morees un refuerzo, no la forma de cumplir 1.4.3.- El tema oscuro debe cumplir el mismo contraste; organízalo con variables y
color-scheme, y prueba con emulación y con un tema de contraste real.
Comprueba lo que has aprendido
Esta lección se puede leer libremente. Para hacer su test de 3 preguntas, los ejercicios prácticos con páginas reales, guardar tu avance y optar al examen y al certificado, matricúlate en el curso.