Lección 6 de 10 · 12 min de lectura · Revisado el 26/10/2026
Estados visibles en CSS: contraste, foco, colores forzados y reflow
Hasta ahora nos hemos ocupado de lo que el formulario dice en el código. Esta lección se ocupa de lo que muestra en pantalla. Un campo bien etiquetado puede seguir siendo inaccesible si su borde casi no se ve, si el foco desaparece, si los errores solo cambian de color o si a 400 % de zoom las etiquetas se separan de sus campos. En el nivel 2 (cursos N2-C3 y N2-C4) vimos estas decisiones desde el diseño; aquí las implementamos en CSS sin romper nada y repasamos los criterios que las regulan: 1.4.11 Contraste no textual, 2.4.7 Foco visible, 1.4.4 Cambio de tamaño del texto, 1.4.10 Reajuste de los elementos, 1.4.12 Espaciado del texto, 2.5.8 Tamaño del objetivo (mínimo) y 1.4.13 Contenido con hover o foco.
Que un campo se vea como un campo
El criterio 1.4.11 (AA) exige una relación de contraste de al menos 3:1 con los colores adyacentes para la información visual necesaria para identificar un componente y sus estados. En un campo de texto, lo que suele permitir identificarlo es el borde. Si ese borde es gris claro sobre fondo blanco, para muchas personas con baja visión el formulario es una página con etiquetas flotando sobre nada.
Ejemplo
Incorrecto: un borde #CCCCCC sobre blanco tiene una relación de 1,6:1, y un campo identificado solo por un fondo #F5F5F5 sobre blanco se queda en 1,1:1.
input { border: 1px solid #ccc; }
.campo-plano { border: 0; background: #f5f5f5; }Correcto: #767676 sobre blanco da 4,5:1, de sobra para el 3:1 exigido. Un borde de 2 píxeles, además, se distingue mejor.
input, select, textarea {
border: 2px solid #767676;
border-radius: 4px;
}Lo mismo vale para el contorno de las casillas de verificación y de los botones de opción personalizados, y para el indicador que muestra que están marcados. Los componentes deshabilitados están exentos del requisito de contraste, pero eso no es una invitación a hacerlos invisibles: la persona tiene que saber que el campo existe aunque no pueda usarlo.
Estados: foco, error, marcado
Cada estado debe poder percibirse sin depender solo del color (1.4.1 Uso del color) y con contraste suficiente. La tabla resume cómo resolverlo en CSS.
| Estado | Qué exigir | Cómo hacerlo |
|---|---|---|
| Foco | Indicador visible siempre que se use el teclado (2.4.7) | :focus-visible con outline de 2 px o más y outline-offset |
| Error | Texto del error y algo más que el color en el campo | Selector [aria-invalid="true"]: borde más grueso, icono y mensaje en texto |
| Marcado | Una forma (tic, punto) además del color de relleno | accent-color o un dibujo en :checked con contraste 3:1 |
| Deshabilitado | Distinguible, aunque esté exento de contraste | Opacidad moderada y cursor; nunca ocultarlo |
Un detalle que ahorra muchos fallos: engancha el estilo de error al atributo ARIA, no a una clase aparte. Así es imposible que el campo se vea rojo sin estar marcado como no válido para el lector, o al revés.
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
outline: 3px solid #1a4fa0;
outline-offset: 2px;
}
input[aria-invalid="true"] {
border: 3px solid #b00020; /* 7,3:1 sobre blanco */
}Error frecuente
El clásico input:focus { outline: none; } heredado de una hoja de estilos de reseteo, a veces compensado con un cambio sutil de color del borde. Quien navega con teclado pierde la pista del campo en el que está. Si el diseño quiere otro indicador, sustitúyelo, no lo quites. En formularios largos vigila también 2.4.11 Foco no oculto (mínimo): una barra fija inferior («Total: 45 € Continuar») o un aviso de cookies pueden tapar por completo el campo enfocado. Reserva espacio con scroll-padding-bottom en el contenedor que se desplaza. El curso N3-C3 trata el foco en profundidad.
Modo de colores forzados
Muchas personas con baja visión o sensibilidad a la luz usan los temas de contraste de Windows. En ese modo, el navegador sustituye tus colores por los del sistema y aplica la consulta @media (forced-colors: active). Dos efectos rompen formularios con frecuencia:
- Las sombras (
box-shadow) se eliminan. Un anillo de foco hecho solo con sombra desaparece por completo. - Los fondos se sustituyen. Una casilla personalizada que muestra el estado «marcado» solo con un fondo de color deja de distinguirse de una vacía.
La solución es mantener siempre un outline o un borde, aunque sea transparente en el modo normal: en colores forzados el sistema le da color y vuelve a verse.
.boton:focus-visible {
box-shadow: 0 0 0 4px #1a4fa0;
outline: 2px solid transparent; /* visible en colores forzados */
}
@media (forced-colors: active) {
.casilla-propia:checked::after {
forced-color-adjust: none; /* respeta este fondo… */
background: CanvasText; /* …con un color del tema del sistema */
}
}Tamaño, zoom y reflow
Los formularios son especialmente frágiles cuando se amplía el texto o se estrecha la ventana:
- 1.4.4 (AA): el texto debe poder ampliarse al 200 % sin perder contenido. Un
inputconheight: 32pxfijo corta el texto al ampliarlo. Usapaddingymin-heightenrem, y deja que la altura crezca. - 1.4.10 Reajuste de los elementos (AA): a 320 píxeles CSS de ancho (equivalente a 1280 píxeles con zoom al 400 %) no debe hacer falta desplazarse en horizontal. La maquetación con etiquetas a la izquierda y campos a la derecha suele romperse: con zoom, la etiqueta queda a un lado de la pantalla y el campo fuera de la vista. Coloca las etiquetas encima de los campos y usa
max-width: 100%en los controles. - 1.4.12 Espaciado del texto (AA): si la persona aumenta interlineado y espaciado, las etiquetas y los mensajes de error no deben cortarse. Evita alturas fijas y
overflow: hiddenen esos contenedores. - 2.5.8 Tamaño del objetivo (mínimo) (AA): los objetivos deben medir al menos 24 × 24 píxeles CSS o tener espacio suficiente alrededor. Una casilla nativa sin modificar queda exenta porque su tamaño lo decide el navegador; si la redibujas a 16 píxeles, la exención se pierde. En cualquier caso, la etiqueta asociada amplía el área en la que se puede pulsar.
Un consejo de diseño que también es de accesibilidad: el ancho del campo sugiere la longitud esperada. Un campo de código postal tan ancho como el de la dirección no ayuda a nadie; uno de 6 caracteres de ancho, sí.
Ayudas emergentes e instrucciones sensoriales
El icono de información junto a un campo que muestra una burbuja al pasar el ratón está sujeto a 1.4.13 (AA): la burbuja debe poder cerrarse sin mover el puntero (normalmente con Escape), debe poder recorrerse con el puntero sin que desaparezca y debe permanecer hasta que la persona la cierre o retire el puntero o el foco. Además, el icono debe ser un botón alcanzable con teclado. Siempre que quepa, es mejor mostrar la ayuda como texto visible asociado con aria-describedby.
Y cuidado con las instrucciones que dependen de la forma, el color o la posición, que incumplen 1.3.3 Características sensoriales (A) cuando son la única referencia: «Los campos en rojo son obligatorios», «Pulsa el botón verde», «Rellena los datos de la columna derecha».
Pruébalo tú
Abre un formulario en Chrome con la ventana a 1280 píxeles de ancho y pulsa Ctrl++ hasta llegar al 400 %. ¿Ves cada etiqueta junto a su campo sin desplazarte en horizontal? Después, en las herramientas para desarrolladores, abre el panel Rendering y emula forced-colors: active: recorre el formulario con Tab y comprueba que el foco y las casillas marcadas siguen viéndose.
Resumen
- El borde o el indicador que identifica un campo y sus estados necesita contraste de 3:1 (1.4.11).
- Nunca elimines el
outlinesin sustituirlo; usa:focus-visibley evita que barras fijas tapen el campo enfocado (2.4.11). - Engancha el estilo de error a
[aria-invalid="true"]y añade texto e icono, no solo color. - En colores forzados desaparecen sombras y fondos: mantén siempre un borde u
outline. - Etiquetas encima, alturas flexibles en
remy objetivos de 24 × 24 px mínimo para soportar zoom, reflow y uso táctil.
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.