Volver a las notas

ariaNotify(): habla al lector de pantalla sin trucos

8 de noviembre de 2026·
accesibilidadjavascriptariawebdev
Demo en vivoAbrir a pantalla completa

Para que un lector de pantalla dijera "Borrador guardado" había que esconder un <div aria-live> vacío en algún rincón de la página y escribir texto dentro. Desde septiembre de 2026 hay un método de verdad para eso en todos los navegadores principales: element.ariaNotify("Borrador guardado").

Qué es y por qué importa

En una interfaz moderna pasan muchas cosas que quien ve la pantalla capta de un vistazo: el contador del carrito pasa de 2 a 3, aparece un "Guardado" pequeñito en una esquina, un icono se pone rojo cuando se cae la conexión. Quien usa un lector de pantalla no se entera de nada de eso si la página no lo dice en voz alta.

La herramienta habitual eran las regiones live de ARIA. Funcionan, pero tienen letra pequeña. MDN lo resume bien: una región live solo puede anunciar algo después de que cambie el DOM, y lo que lee es el contenido actualizado de ese nodo. Así que todos acabamos con el mismo apaño: un nodo oculto visualmente con aria-live al que vaciamos y rellenamos el texto solo para que lo lea. MDN describe ese patrón como "ineficiente y propenso a errores", y quien haya tenido que averiguar por qué un mensaje se lee dos veces, o ninguna, sabe a qué se refiere.

ariaNotify() elimina ese apaño. Llamas a un método, le pasas el texto y el navegador se lo entrega a la tecnología de apoyo. Sin nodos auxiliares, y el mensaje no tiene por qué coincidir con nada de lo que hay en pantalla.

Es Baseline (recién disponible) desde septiembre de 2026: Chrome y Edge 141, Firefox 150 y Safari 27.

Cómo funciona

La especificación WAI-ARIA lo define como un mixin que incluyen tanto Element como Document:

element.ariaNotify(announcement);
element.ariaNotify(announcement, { priority: "high" });
document.ariaNotify(announcement);

Devuelve undefined. La única opción es priority, con dos valores:

  • "normal" (el valor por defecto): se lee después de lo que el lector esté diciendo en ese momento. Equivale más o menos a aria-live="polite".
  • "high": interrumpe y se lee de inmediato. Equivale más o menos a aria-live="assertive".

No necesita activación del usuario, así que puedes llamarlo desde un temporizador o cuando llega una respuesta de red. Justo por eso conviene usarlo con mesura.

En la demo de arriba, cada botón de la "app" llama a ariaNotify() sobre sí mismo. Esta es la función que usa, con plan B incluido:

function notify(el, message, priority = "normal") {
  if ("ariaNotify" in el) {
    el.ariaNotify(message, { priority });
  } else {
    // Plan B: una región aria-live oculta visualmente, que se vacía y se rellena
    const region = document.getElementById(priority === "high" ? "assertive" : "polite");
    region.textContent = "";
    setTimeout(() => { region.textContent = message; }, 50);
  }
}

saveButton.addEventListener("click", (e) => {
  notify(e.currentTarget, "Draft saved at 10:42.");
});
offlineButton.addEventListener("click", (e) => {
  notify(e.currentTarget, "Connection lost. Your changes will sync when you are back.", "high");
});

El panel derecho de la demo es un lector de pantalla virtual: no puede oír lo que dice el tuyo, pero dibuja el modelo que describe MDN. Pulsa "Subir 3 archivos" y verás cómo se ponen en cola los tres mensajes; pulsa "Perder la conexión" mientras habla y el de prioridad alta lo corta y pasa delante. Si marcas "Leer en voz alta", la síntesis de voz del navegador los lee para que también los oigas. Si tienes VoiceOver, NVDA o TalkBack activos, el aviso real les llega igualmente.

Sobre qué elemento llamarlo

No es solo cuestión de gustos. Según la especificación, si el elemento está excluido del árbol de accesibilidad, la llamada se ignora. MDN avisa de que, según el navegador, eso incluye contenedores con poco valor semántico como <html> o <body>. Lo más seguro es llamarlo sobre el elemento con el que el usuario acaba de interactuar, como el botón de la demo, o sobre document.

El idioma lo pone el elemento

No hay parámetro lang. La especificación dice que el aviso hereda el idioma y la dirección del elemento sobre el que se llama, así que el lector elige la voz según el atributo lang más cercano. Si el mensaje está en otro idioma que la página, llámalo desde un elemento que lo declare. En la demo, el último botón lleva en lang el idioma contrario al de la página:

const note = document.createElement("div");
note.lang = "es";
document.body.append(note);
note.ariaNotify("Tu pedido está listo.");

Soporte y trampas

  • Detección: "ariaNotify" in Element.prototype. Las versiones anteriores de Safari no lo tienen (en mis pruebas, WebKit 26.5 devuelve false), así que de momento mantén la región live como alternativa. La demo muestra un aviso y cambia a ella sola.
  • No cuentes con una cola: MDN es claro en que algunos lectores leen varios avisos seguidos, pero no está garantizado y a menudo solo se lee el último. Si tienes dos cosas que decir, dilas en una sola llamada.
  • Las regiones live siguen mandando: según MDN, los avisos de aria-live tienen prioridad sobre los de ariaNotify(). Si mezclas ambos, la región live va primero.
  • macOS y ChromeOS: los datos de compatibilidad de MDN indican que con VoiceOver un aviso puede perderse si a la vez salta otro evento de accesibilidad, y que en ChromeOS el método existe en Chrome pero los avisos nunca se leen.
  • Iframes: su uso lo controla la política de permisos aria-notify. Su lista permitida por defecto es *, así que funciona dentro de iframes salvo que alguien lo bloquee, y cuando está bloqueado los avisos fallan en silencio.
  • No abuses: que no necesite activación del usuario es cómodo, pero cada aviso interrumpe a alguien que está escuchando. Un mensaje por evento relevante, corto y útil.

Qué vigilar

  • Cómo gestiona cada lector de pantalla la cola y la prioridad high. Ahí es donde más va a variar el comportamiento durante un tiempo, así que merece la pena probar con NVDA, JAWS y VoiceOver en lugar de fiarse de la simulación.
  • Cuándo la parte de navegadores sin soporte sea lo bastante pequeña como para quitar la región live de tu proyecto.
  • La especificación solo define normal y high por ahora. Si se añaden más opciones, aparecerán en el diccionario AriaNotificationOptions.

Fuentes