Mensajes de estado
Los mensajes de estado — confirmaciones, errores, actualizaciones de progreso, recuentos de resultados de búsqueda — deben anunciarse a la tecnología de apoyo sin desplazar el foco. Utilizar role=status, role=alert o aria-live en una región que ya exista en el DOM.
Qué exige este criterio
Cuando la página informa al usuario de que algo ha ocurrido — «Artículo añadido al carrito», «3 resultados encontrados», «Conexión perdida», «Guardando…» — ese mensaje debe llegar a los usuarios de lector de pantalla sin obligar al foco a desplazarse. La información debe estar determinada programáticamente como un estado, de modo que la tecnología de apoyo pueda captarla y anunciarla.
Las tres categorías que WCAG distingue:
- Éxito / finalización — «Perfil guardado», «Correo enviado».
- Resultados de una acción — «12 resultados», «Sin coincidencias».
- Estado de la aplicación — «Guardando…», «Reconectando», «Carga al 40 %».
Cómo cumplirlo
- Colocar una región dinámica en el DOM al cargar la página — un elemento vacío con
role="status"(educada) orole="alert"(asertiva). Al actualizar, escribir el nuevo texto en su interior. - Para confirmaciones no críticas y recuentos de resultados, usar
role="status"oaria-live="polite". Los lectores de pantalla esperan a que el usuario esté inactivo y luego anuncian el mensaje. - Para mensajes críticos — errores en el envío de formularios, pérdida de conexión, sesión a punto de expirar — usar
role="alert"oaria-live="assertive". El anuncio interrumpe la lectura. - Las notificaciones emergentes (toasts) necesitan una región dinámica. El contenedor de la notificación debe existir en el DOM antes de que aparezca la notificación, con
aria-liveconfigurado, y el texto de la notificación se inyecta como nodo hijo. - Combinar
aria-liveconaria-atomic="true"si se desea que la región completa se relea en cada actualización, no solo los nodos modificados. - Para los errores de formulario, el mensaje de error en línea puede usar
role="alert", o bien desplazar el foco a un resumen al principio del formulario — pero no ambas opciones a la vez; los usuarios solo necesitan escucharlo una vez.
Fallos habituales
- Notificaciones emergentes renderizadas en un elemento que no existía antes de la notificación — el observador de la región dinámica nunca se adjunta y no se anuncia nada.
- Un banner de éxito que se inserta pero reside fuera de cualquier región
aria-live— visible para los usuarios con visión, invisible para los usuarios de lector de pantalla. - El recuento de resultados de búsqueda («Mostrando 12 de 340») que se actualiza silenciosamente tras aplicar filtros. Los usuarios vuelven a las pestañas de resultados sin saber si algo ha cambiado.
- Validación de formulario que actualiza un
<span class="error">en línea sinrole="alert"niaria-live— el error aparece, el lector de pantalla guarda silencio. - Usar
aria-live="assertive"para todas las actualizaciones de estado. Las interrupciones constantes llevan a los usuarios de lector de pantalla a desactivar la página. - Desplazar el foco a un mensaje de estado que no es un encabezado ni un elemento interactivo — el foco aterriza en un elemento sin tabulación y los usuarios de teclado pierden su posición.
- Los indicadores «Guardando…» / «Guardado» que cambian una clase CSS pero nunca actualizan el contenido de texto dentro de una región dinámica.
Por qué es importante
Los mensajes de estado son el punto donde las aplicaciones de una sola página modernas fallan con más frecuencia. La página nunca se recarga, el foco casi nunca se mueve, y la única señal de que algo ha ocurrido es un cambio visual — inútil para cualquier persona que no esté mirando la pantalla. El criterio 4.1.3 impone la paridad: si un usuario con visión puede leer «Añadido al carrito», un usuario de lector de pantalla puede escucharlo. La solución casi siempre es económica (una región dinámica, rellenada en la actualización) y su ausencia casi siempre rompe flujos esenciales — pago, búsqueda, envío de formularios, chat en tiempo real.