Addaw, ir a inicio Donar

Lección 8 de 10 · 11 min de lectura · Revisado el 26/10/2026

Regiones activas: aria-live, role="status" y role="alert" (4.1.3)

Las interfaces modernas cambian sin recargar: aparece «Producto añadido al carrito», el contador de resultados pasa de 120 a 8 al aplicar un filtro, una barra de progreso avanza, un chat recibe un mensaje. Quien ve la pantalla lo percibe de inmediato. Quien usa un lector de pantalla está escuchando otra parte de la página y no se entera, salvo que el código lo anuncie. Para eso existen las regiones activas (live regions), y el criterio 4.1.3 Mensajes de estado (AA, introducido en WCAG 2.1) exige usarlas: los mensajes de estado deben poder ser determinados por programa mediante rol o propiedades, de modo que las tecnologías de apoyo los presenten sin que reciban el foco.

Qué es un mensaje de estado

WCAG define mensaje de estado como un cambio de contenido que informa a la persona del éxito o resultado de una acción, del estado de espera de la aplicación, del progreso de un proceso o de la existencia de errores, y que no supone un cambio de contexto. Si el foco se mueve al mensaje (por ejemplo, a un diálogo o a un resumen de errores que recibe el foco), ya no es un mensaje de estado en el sentido de 4.1.3: la persona lo leerá porque está ahí. El criterio cubre precisamente lo que aparece sin mover el foco.

Las herramientas

  • aria-live="polite": el lector anuncia el cambio cuando termine lo que esté diciendo. Es la opción por defecto para casi todo.
  • aria-live="assertive": interrumpe inmediatamente. Solo para errores o avisos que requieren atención urgente.
  • role="status": equivale a aria-live="polite" con aria-atomic="true". Para confirmaciones, contadores, estados de carga.
  • role="alert": equivale a aria-live="assertive" con aria-atomic="true". Para errores y avisos importantes.
  • role="log": para flujos donde se añade contenido al final (chat, registro de actividad); polite y no atómico.
  • aria-atomic="true": anuncia toda la región, no solo el fragmento que cambió. Imprescindible cuando el mensaje solo tiene sentido completo («3 de 10 archivos subidos»).
  • aria-relevant: qué cambios se anuncian (additions, removals, text); el valor por defecto, additions text, es casi siempre el adecuado y rara vez hay que tocarlo.
  • aria-busy="true": suspende los anuncios mientras una región se está actualizando por partes; al pasar a false, se anuncia el resultado.

Ejemplo

Contador de resultados de un buscador con filtros:

<p id="contador" role="status"></p>
<ul id="resultados">…</ul>
function actualizarResultados(lista) {
  pintarLista(lista);
  document.getElementById('contador').textContent =
    `${lista.length} resultados encontrados`;
}

Al cambiar un filtro, el lector termina de leer lo que estuviera leyendo y anuncia «8 resultados encontrados». La persona no tiene que ir a buscar el número. Fíjate en que el párrafo existe vacío desde el principio y que solo se cambia su texto.

Las reglas que hacen que funcione

Las regiones activas son frágiles: pequeños detalles de implementación hacen que no se anuncie nada o que se anuncie demasiado. Estas reglas evitan la mayoría de los fallos:

  1. La región debe existir en el DOM antes del cambio. Los lectores de pantalla registran las regiones activas al construir el árbol; si creas el <div role="status"> y le pones el texto en la misma operación, muchos no lo anuncian. Crea el contenedor vacío al cargar la página e inserta el texto después.
  2. Cambia el contenido, no la visibilidad. Quitar display:none a una región que ya tenía texto no cuenta como cambio en varios lectores. Inserta o modifica el texto.
  3. Una región, un mensaje a la vez. Varias regiones hablando a la vez se pisan. Lo habitual es tener una región status y una alert globales, vacías, en la plantilla, y escribir en ellas desde cualquier componente.
  4. Vacía la región tras unos segundos si vas a reutilizarla, para que el mismo mensaje repetido se anuncie de nuevo (algunos lectores no anuncian un texto idéntico al anterior) y para que no se lea al navegar por la página.
  5. Sé breve. Una región activa no es un lugar para párrafos; una frase corta y concreta.
  6. No pongas aria-live en contenedores grandes (todo el <main>, una tabla entera): cada cambio provocará lecturas interminables.
  7. assertive es la excepción, no la norma. Reserva role="alert" para errores que impiden continuar y avisos de tiempo (sesión a punto de expirar).

Error frecuente

// Incorrecto: la región se crea con el mensaje dentro
const aviso = document.createElement('div');
aviso.setAttribute('role', 'alert');
aviso.textContent = 'Error al guardar';
document.body.appendChild(aviso);
// Correcto: el contenedor ya existe en el HTML, vacío
// <div id="aviso-error" role="alert"></div>
document.getElementById('aviso-error').textContent = 'Error al guardar';

Hay lectores que sí anuncian el primer caso, pero no todos ni siempre. El segundo funciona de forma consistente.

Casos típicos y la herramienta adecuada

SituaciónSolución
«Añadido al carrito», «Guardado», «Copiado»role="status"
Número de resultados tras filtrarrole="status"
Error de validación al salir de un campo (sin mover el foco)Mensaje asociado con aria-describedby; opcionalmente una región status que lo anuncie
Error del servidor que impide continuarrole="alert"
La sesión expira en 2 minutosrole="alert" (o un diálogo con foco si hay que actuar)
Barra de progreso de una subida<progress> o role="progressbar" con aria-valuenow; anuncios en status cada 25 %, no cada 1 %
Mensajes nuevos en un chatrole="log"
«Cargando…» mientras llegan datosrole="status" con el texto «Cargando resultados» y aria-busy en la región que se actualiza
Caracteres restantes en un textarearole="status" actualizado con moderación (cada 10 caracteres o al pararse de escribir), no en cada tecla

Cuándo no usar una región activa

Si la persona debe actuar sobre lo que aparece (confirmar, corregir, elegir), mueve el foco a ello en lugar de anunciarlo: un diálogo modal, un resumen de errores enfocable. Y si el cambio es la consecuencia directa y evidente de la acción sobre el elemento con foco (marcar una casilla, cambiar una pestaña), el propio cambio de estado del elemento ya se anuncia; una región activa duplicaría el mensaje.

Punto clave

Un par de regiones vacías en la plantilla base (<div role="status"> y <div role="alert">), una función anunciar(texto, urgente) que escriba en la adecuada y la vacíe pasados unos segundos, y disciplina para usar status casi siempre: con eso se cumple 4.1.3 en toda la aplicación.

Cómo comprobarlo

  • Con NVDA o VoiceOver activo, provoca cada mensaje de estado sin mover el foco y comprueba que se anuncia una sola vez y completo.
  • Inspecciona el HTML inicial: las regiones deben existir vacías antes de la interacción.
  • Busca aria-live en contenedores grandes y assertive injustificados.
  • Prueba el mismo mensaje dos veces seguidas: debe anunciarse ambas.

Resumen

  • 4.1.3 exige que los mensajes que aparecen sin mover el foco sean anunciados por las tecnologías de apoyo mediante rol o propiedades ARIA.
  • role="status" (polite, atómico) para casi todo; role="alert" (assertive) solo para errores y urgencias; role="log" para flujos.
  • La región debe existir vacía en el DOM antes de insertar el texto; cambia el contenido, no la visibilidad.
  • Pocas regiones, mensajes cortos, sin aria-live en contenedores grandes.
  • Si la persona debe actuar, mueve el foco en lugar de anunciar.

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.