Douze. C’est le nombre d’interruptions vocales que NVDA a déclenchées sur un widget de conversation observé récemment, pour une réponse d’une quarantaine de mots affichée en flux progressif. Chaque paquet de texte inséré dans le DOM redéclenchait une lecture, et l’utilisatrice de lecteur d’écran n’entendait qu’une bouillie de fragments coupés.
Le symptôme ne vient pas de la pertinence de la réponse générée, mais de la façon dont elle est injectée dans la page. Une zone marquée aria-live="polite" qui reçoit du texte toutes les cinquante millisecondes se comporte comme une zone qui crie en continu : la technologie d’assistance tente de suivre, échoue, et finit par abandonner la lecture au milieu d’une phrase.
Ce qu’on observe sur le terrain
Le motif revient sur plusieurs implémentations différentes, qu’il s’agisse d’un plugin de support client ou d’un assistant maison branché à une API de complétion. Le conteneur de réponse est une <div> avec aria-live="polite", et chaque jeton reçu du flux (au sens des tokens retournés par l’API) est ajouté au textContent existant. Trois désagréments s’installent :
- Le lecteur d’écran relance une annonce à chaque mutation, ce qui produit un débit haché et incompréhensible.
- Le focus clavier, s’il était posé sur le champ de saisie, en est parfois arraché par un script trop zélé qui rappelle
.focus()sur le conteneur de réponse. - Une fois le flux terminé, rien ne signale la fin de la réponse : l’utilisateur ne sait pas s’il doit continuer à écouter ou reprendre la main.

Pourquoi c’est un problème concret
La spécification WAI-ARIA prévoit les régions live précisément pour annoncer des changements de contenu asynchrones, mais elle part du principe que ces changements sont ponctuels : un message de confirmation, un compteur qui se met à jour, une erreur de formulaire. Un flux de texte qui grossit plusieurs fois par seconde n’a jamais été le cas d’usage visé, et aucune technologie d’assistance ne le gère élégamment par défaut.
Il y a aussi une question de confiance. Un contenu géré par un modèle de langage doit rester vérifiable et navigable comme n’importe quel autre contenu : si la structure sonore de la page devient imprévisible pendant la génération, la personne malvoyante ou aveugle perd un repère essentiel, celui de savoir où elle se trouve dans l’échange.
Le correctif qui fonctionne
La solution la plus fiable observée jusqu’ici tient en trois décisions de conception :
- Découpler l’affichage visuel du flux (qui peut rester progressif, c’est un choix produit légitime) de l’annonce sonore, qui doit rester ponctuelle.
- Ne mettre à jour la région live qu’une seule fois, quand la réponse est complète, ou par phrases entières plutôt que par jeton.
- Garder le focus clavier sur le champ de saisie pendant toute la génération, sauf action explicite de l’utilisateur.
let buffer = '';
let sentenceBoundary = /[.!?]\s/;
function onToken(token) {
buffer += token;
renderVisual(buffer); // mise à jour visuelle libre, sans contrainte
const match = buffer.match(sentenceBoundary);
if (match) {
const region = document.getElementById('reponse-live');
region.textContent = buffer.slice(0, match.index + 1);
}
}
function onStreamEnd() {
const region = document.getElementById('reponse-live');
region.textContent = buffer + ' Réponse terminée.';
}
Cette approche par phrase entière réduit drastiquement le nombre d’interruptions : sur le même test, on passe de douze annonces à trois ou quatre, correspondant chacune à une unité de sens complète.
Un détail souvent oublié : l’état de chargement
Avant même le premier jeton, il faut annoncer que la génération commence. Un role="status" distinct, avec un texte du type « Réponse en cours de génération », évite que l’utilisateur pense que le champ de saisie n’a pas réagi à son message. Ce statut disparaît ou se remplace dès l’arrivée du premier fragment de texte utile.
Conseil maison : testez toujours au clavier ET au lecteur d’écran activé simultanément. Un flux qui semble fluide à l’œil peut être totalement inaudible.
En résumé
Un chat IA en flux continu n’est pas condamné à être inaccessible, mais il exige de traiter la couche sonore séparément de la couche visuelle. Découper les annonces par unité de sens, stabiliser le focus et signaler clairement le début et la fin de la génération suffisent à transformer une expérience frustrante en un échange que l’on peut suivre du début à la fin, quel que soit le mode de lecture utilisé.