Aller au contenu

La principale différence entre un site web et une application web est… sujette à débat. Dans l’ensemble, je dirais que plus il y a de liens, plus c’est un site ; et que plus il y a de boutons, plus c’est une application. Si cela n’inclut qu’une seule page avec un formulaire, c’est probablement une sorte de site. S’il s’agit principalement de formulaires, vous pouvez parler d’application. Dans tous les cas, votre « produit » web n’est en réalité que du contenu interactif, consommé et transmis par une application que nous appelons un « navigateur ».

Une chose est certaine : une page web ressemble plus à une application de bureau à sa façon de se comporter. Les pages web qui subissent des changements au fur et à mesure que vous les utilisez sont quelque chose de tout à fait différent des pages web qui ne font que se recharger lorsque vous cliquez sur les hyperliens.

Parfois, c’est l’utilisateur ou l’utilisatrice qui sera à l’origine d’un changement d’état. D’autres fois, ce sera un autre usager ou une autre usagère qui affectera l’application à distance, et en temps réel. Plus occasionnellement, l’application pourra être sujette à des événements extérieurs et temporels, indépendants de toute action humaine. Dans tout les cas, il est important que les utilisateurs et utilisatrices soient tenus au courant des changements d’état, et la problématique est donc de les avertir.

Dans cet article, j’examinerai les possibles moyens de notification et j’expliquerais pourquoi elles peuvent rassurer les usagers et les usagères d’applications web ; tout ça de manière inclusive.


Attirer l’attention

L’un des plus grands défis dans la création d’interfaces agréables à utiliser est de savoir quand attirer l’attention sur quelque chose. Une remontée d’informations excessive sera sans doute considérée comme une nuisance, mais une remontée d’informations insuffisante pourra donner à vos utilisateurs et utilisatrices l’impression qu’ils leur manque des points essentiels. C’est parfois très perturbant : même quand il n’y a vraiment aucune information à remonter, il y a ce besoin de le « savoir ».

Et puis il y a le comment. D’une manière générale, il y a deux types de messages qui nécessitent deux approches différentes pour être accessibles :

  1. les messages qui demandent aux utilisateurs et utilisatrices d’interagir ;
  2. les simples messages informatifs.

Typiquement, un message demandant de faire quelque chose constituera le contenu d’une fenêtre de dialogue (ou l’apparition d’un élément au sein du contenu). Cette fenêtre doit alors être accompagnée d’un certains nombre de boutons d’action. Et puisque l’utilisateur ou l’utilisatrice devra interagir avec ces boutons, le focus doit être déplacé dans cette boîte de dialogue.

Pour les besoins de cet article, ce que j’entendrais par « notification » sera pour les messages qui vous permettent simplement de savoir ce qui se passe. Cela peut être pour que vous puissiez choisir d’agir plus tard, ou pour vous assurer qu’un événement a eu lieu.

En termes d’accessibilité pour un lecteur d’écran et au clavier, il est important que le focus ne soit pas fait vers de tels messages. S’il n’y a aucune action à faire, vous ne mettez d’outil dans la main de personne. Malgré cela, le déplacement de focus s’est imposé comme une « bonne pratique ». Pourquoi ? Parce que la focalisation sur un élément était, historiquement, le moyen le plus fiable d’obtenir que cet élément et son contenu soient annoncés dans des lecteurs d’écran. Donner le focus à une notification, déclenchait donc une annonce dans le lecteur d’écran.

Le focus une fois déplacé vers une notification, déclenche une annonce dans le lecteur d’écran.
« C’est super. Mais où suis-je maintenant ? Que faire ? »

Heureusement, nous avons de nos jours des live regions afin de parer à cette mauvaise habitude.

Introduction aux live regions

Nous avons déjà utilisé des live regions sur ce blog, mais je vais prendre le temps de vous redonner un aperçu général ici.

Une live region n’est qu’un conteneur qui fixe un périmètre autour d’un contenu live : un contenu qui sera donc annoncé – par un logiciel de lecture d'écran – sans interaction de l’utilisateur ou de l’utilisatrice et sous certaines conditions. Par défaut, une live region annoncera tout ce qui est ajouté ou modifié à l’intérieur de son conteneur.

C’est troublant, mais il existe deux A.P.I. équivalentes pour les live regions : l’attribut aria-live et les rôles ARIA des live regions. Dans la plupart des cas, vous voudrez utiliser soit un role="status", soit un aria-live="polite". L’utilisation simultanée des deux augmente la compatibilité avec différents couples de navigateurs et de technologies d’assistance :

<div role="status" aria-live="polite">  
</div>  

Ajouter « Faites une petite pause ! » dans cette live region (comme illustré plus loin) s’activera immédiatement après l’insertion du nœud texte. Et cela ne fonctionne pas qu’avec les nœuds textes ; cela peut être du code.

<div role="status" aria-live="polite">  
  Faites une petite pause !
</div>  

L’arrivée du message « Faites une petite pause ! » dans l’interface peut maintenant être vue et entendue simultanément, créant une correspondance entre l’expérience visuelle et l’expérience auditive (assistée par lecteur d’écran). Ce n’est pas la même expérience, mais c’est une expérience comparable : elle sert le même but.

Et tout le monde devrait régulièrement s’éloigner de son écran.

Les live regions invisibles

Parfois, pour créer une expérience globale similaire, un peu d’information sonore supplémentaire peut être nécessaire. Par exemple, lorsqu’un usager ou une usagère clique sur un bouton « ajouter au panier », l’interface peut répondre animant un produit se déplaçant dans le panier. Une traduction directe de ceci peut être un bruit de glissement suivi d’un bruit métallique, mais je pense qu’ici une live region visuellement cachée indiquant « produit ajouté avec succès » (ou quelque chose de similaire) serait beaucoup plus clair.

Un paquet de bonbons pour chiens au quinoa est déplacé au dessus du panier d’achat, déclenchant la lecture de « Bonbons pour chiens au quinoa ajoutés au panier » quand ils sont ajoutés.

Ajouter une live region à une page contenant déjà le contenu que vous souhaitez annoncer n’est pas fiable. Il faut au moins un certain temps entre l’ajout d’une live region au DOM et l’ajout de contenu dans la live region.

Pour faire dire des choses aux lecteurs d’écran simplement pendant que vous gérez les événements dans vos scripts, j’ai créé un petit module. En voici un exemple d’utilisation, avec les paramètres par défaut :

const liveRegion = new OnDemandLiveRegion()

liveRegion.say('Faites une petite pause !')

Le script créé des live regions ARIA cachées et les peuple à la volée, il rend donc la communication avec les lecteurs d’écran triviale du point de vue de la procédure. Cependant, dans la plupart des cas – et dans le cas des messages d’état en particulier – nous voulons communiquer avec les utilisateurs et les utilisatrices. Pas uniquement ceux et celles qui possèdent des lecteurs d’écran ou au contraire ceux et celles n’en utilisant pas ; mais tout le monde. Les live regions facilitent les communications visuelle et auditive simultanées.

Une messagerie instantanée

Dans les applications de messageries instantanées (des outils comme Slack, où tout se passe en temps réel), il y a de nombreuses choses à remonter. Par exemple :

Tous ces types de messages arrivant en permanence vont rapidement devenir perturbant et irritants, surtout s’ils sont remontés vocalement. Vous pouvez détourner les yeux, mais pas les oreilles.

Nous devons faire deux ou trois choses pour rendre l’expérience plus digeste :

Restreindre les messages en fonction du contexte

J’ai remarqué récemment alors que j’utilisais un lecteur d'écran pour consulter un onglet de mon navigateur que je pouvais entendre les mises à jour provenant d’un autre onglet ouvert, même si je ne l’affichais pas. La seule solution à été de fermer l’onglet caché. Ce qui n’était pas idéal, car j’aurais souhaité passer d’un onglet à l’autre.

Deux onglets de navigateur : celui au premier plan correspondant à la page ouverte ; le second en arrière plan est en train de lire un « bla bla bla ».

Pour un internaute voyant, l’invisible est inconnu. Peu lui importe que les messages continuent de s’afficher. Mais, pour les utilisateurs ou utilisatrices de lecteurs d'écran (aveugles ou non), nous devons rendre muettes les remontées des onglets cachés. Nous pouvons le faire en interrogeant document.hidden après un événement visibilitychange issu de l’A.P.I. de visibilité des pages, puis en passant la live region d’active à inactive. Les live regions inactivent se voient alors attribuées d’un role="none" et/ou d’un aria-live="off".

Voici comment ça fonctionne :

const notifications = document.getElementById('notifications');

document.addEventListener('visibilitychange', () => {  
  let setting = document.hidden ? ['none', 'off'] : ['status', 'polite'];

  notification.setAttribute('role', setting[0]);
  notification.setAttribute('aria-live', setting[1]);
});

Les configurations sont multiples

Il faut de noter que certaines combinaisons entre logiciels de lecture d’écran et navigateurs taisent automatiquement certaines live regions quand elles sont dans des onglets et des fenêtres cachés ou inactives. Cependant, vous ne pouvez pas compter sur le fait que tout vos utilisateurs aient tous ce type de configuration et – quand ce n'est pas le cas – l’expérience sera très déconcertante.

Conversations

Même quand votre onglet ouvert contient une application de messagerie instantanée, vous ne voulez pas être inondé par une multitude de notifications. Visuellement, cela pourrait devenir irritant ; vocalement, cela le sera à coup sûr.

Savoir quand informer votre utilisateur revient à se questionner sur son contexte d’utilisation. Ainsi, un utilisateur ne sera probablement pas intéressés par des notifications concernant les messages d’autres utilisateurs sans rapport à la conversation actuelle, ni par le signalement de l’arrivée en ligne d’autres utilisateurs avec lesquels il n’a aucun historique en commun.

D’un autre côté, si l'utilisateur est en train de rédiger une réponse dans un fil de discussion et qu’un nouveau message apparait entre-temps, il voudra probablement en être informé. Dans ce cas, le message ne se manifeste à vous que si vous êtes un utilisateur voyant. Pour un utilisateur aveugle utilisant un lecteur d’écran, vous devez lui faire remonter cette notification via une live region.

L’attribut aria-relevant permet de contrôler quels types de modifications dans une live region sont dignes d’être lus. Dans ce cas, seuls les messages nouvellement ajoutés sont vraiment intéressants, aussi nous l’avons défini avec aria-relevant="additions" en plaçant cet attribut sur l’élément qui gère le flux des messages.

Des messages apparaissent juste au-dessus du champ texte « Votre message ». Ces messages sont dans un conteneur avec l’attribut aria-relevant configuré pour que seules les nouvelles entrées soient prises en compte. C’est le champ texte qui à le focus.
Quand des nouveaux messages, en gris, apparaissent, seuls leurs contenus, et seulement eux – sans le contenu des autres messages – sont transmis aux lecteurs d’écran.

Les messages supprimés ou édités ne devraient pas non plus être annoncés à nouveau, mais les messages édités devraient eux pouvoir être pris en compte. Par conséquent, le balisage des messages doit être bien formé et clair sémantiquement, en utilisant une structure de liste (<ul>) afin de les regrouper.

<h1>La messagerie instantanée du bien-être</h1>  
<div role="status" aria-live="polite" aria-relevant="additions">  
  <ul class="messages">
    <li>
      <h2>Heydon, <small>il y a 22 minutes</small> :</h2>
      <p>Faites une pause ! Ça fait 15 heures.</p>
    </li>
    <li>
      <h2>Heydon:</h2>
      <p>Oh, je suppose que c’est déjà fait.</p>
    </li>
  </ul>
<div>  
<form>  
   <label for="message">Votre message</label>
   <textarea id="message"></textarea>
   <button type="submit">Publier</button>
</form>  

Quand le dernier élément de la liste est ajouté, les utilisateurs de lecteurs d’écran entendent « Heydon : Oh, je suppose que c’est déjà fait ». On peut se demander alors s’il ne faut pas préfixer chaque message par le mot « Message » afin de permettre une différenciation entre eux et les autres notifications. Nous y reviendrons rapidement.

Si l’utilisateur du lecteur d’écran n’est pas au niveau du champ texte, une amélioration possible serait de lui faire entendre les nouveaux messages que s’il s'adressent directement à lui — ce qui utilisent le « @ », par exemple. Nous ne lésons pas ces utilisateurs ; nous évitons juste de pas les interrompre pendant une autre tâche, sauf quand le message est explicitement du type « hé, j'ai besoin de toi ».

Notifications rapides

Les notifications rapides – des bandeaux colorés contenant des messages qui apparaissent par dessus la page – sont souvent utilisés pour informer les utilisateurs des changements d’état. Une simple live region ARIA suffira pour ces notifications qui ne donnent lieu à aucune action.

Je vous en dirais plus sur la manière de les concevoir juste après, mais assurons nous avant tout qu’ils puisse être éteints. La première chose que je fais quand j’installe une application comme Skype est de désactiver les sons de notification, et j’ai de bonnes raisons à faire cela.

Le panneau de configuration

La conception d’une page regroupant les paramètres de l’application ne demande pas d’avoir fait de hautes études. Ce ne sont que des titres, des sous-titres et des contrôles de formulaires. Mais, si vous n’y faites pas attention, vous pouvez néanmoins abimer toute l’architecture et la terminologie de votre contenu.

Des noms de catégories comme « général » et « contenu » ne signifient pas grand chose par exemple. Et cacher ce que vous considérez subjectivement comme des paramètres avancés derrière un petit lien difficile à localiser, n’aide pas vraiment non plus.

Mieux vaux tout formuler tout de façon descriptive, et tout structurer logiquement. Utilisez les contrôles de formulaire standard tels que les cases à cocher, des boutons radio et des sliders. Le panneau de configuration permet aux utilisateurs de contrôler la façon dont ils utilisent leur application ; n’y pensez pas après coup.

Headings inside legends

When structuring (long) forms, it often helps to group related controls together inside <fieldset> elements. Then <legend> elements can be employed to provide 'group labels'. These are announced when screen reader users enter the fieldset and focus the first control. They give contextual information.

<legend>s tend to supplant headings, because otherwise you'd be labeling sections of the form twice. The trouble is, headings have their own advantages for screen reader navigation.

Fortunately, a recent change to the HTML spec now allows you to author pages with headings inside your <legend>s: the best of both worlds. Here's the sort of structure, we should be going for:

An h1 of settings followed by two sections: Change your password and Notifications, each introduced by h2 headings inside legends and grouped by fieldset containers.

Note that turning off a notification type would mean it no longer occurs visually or aurally (in screen reader output). It's likely that certain notifications would be much less desirable to many screen reader users, and they're more likely to turn them off. But everyone has the same control and can make decisions for themselves. We're not making assumptions for them.

Differentiating message types

Our singular live region may play host to a variety of notification types. Basic information will probably be most common, but there may be warnings, errors, and messages of congratulation — perhaps the user can earn awards for being a helpful member of the community.

The general rule is that any part of an interface differentiated only by style and not content will be inaccessible. Things like shape, color, position are just not enough on their own to define something inclusively. In this case, the MVP for differentiating messages is therefore to preface with terms like "Error:", "Info:", "Congratulations:" or whatever is suitable. A bold style is typical.

Three different message types. A message starting 'congratulations' in green, a message starting 'error' in red and a message starting 'info' in blue.

Should you wish to supplant the text with icons you'll have to be careful they are visually comprehensible, include alternative text for screen reader users, and are still visible where Windows High Contrast Mode is running.

Try an optimized, inline SVG with a fill set to currentColor to honor high contrast mode. For alternative text, aria-label is not recommended because it is not picked up by translation services like Google's. The same, unfortunately, applies to any text (<title> or <text>, say) inside SVGs. The best we can do is insert some visually hidden text just for assistive software. It's ugly markup, but it works.

<div role="status" aria-live="polite">  
  <div class="message award">
    <p>
      <strong>
        <svg viewBox="0 0 20 20" focusable="false">
          <use xlink:href="#star"></use>
        </svg>
        <span class="visually-hidden">Félicitations!</span>
      </strong>
      Vous avez gagné 6 bons points Internet
    </p>
  </div>
</div>  
Une ligne pointillée vide indique l’élément span invisible qui se lit « Félicitations ».
La span caché sera bien sûr complètement invisible. Le focus est montré ici uniquement pour indiquer où il se trouve.

Ignorer les notifications

En tant que consultant en design, je vois souvent des messages de notification avec des petits boutons "✖️" pour les rejeter.

Une notification avec un bouton de fermeture en croix à sa droite.

Bien que je souhaite encourager tout ce qui permet aux utilisateurs d’avoir le contrôle sur l’interface, j’ai des doutes dans le cas présent. Je ne pense pas que la possibilité de rejeter manuellement des notifications soit assez importante pour les déranger ; ce n’est pas quelque chose qui vaut la peine d’être vu ou réfléchit. (Il y a aussi une problématique à gérer le focus lorsque le bouton de fermeture est retiré du DOM après avoir été pressé, comme nous l’avons vu dans la liste des tâches).

À la place, il vaut mieux que les messages disparaissent d’eux-mêmes – après un laps de temps approprié. Voici un petit script qui vous permet de créer des espaces de notifications classés par type (« erreur », « récompenses », ou « informations », par exemple) et d’injecter/supprimer des messages après un certain temps.

function Notifier(type, regionEl, duration) {  
  this.regionEl = regionEl;
  this.duration = duration || 10000;
  this.type = type || 'info';
}

Notifier.prototype.notify = function(message) {  
  let note = document.createElement('p');

  note.innerHTML = `
    <svg viewBox="0 0 20 20" focusable="false">
      <use xlink:href="#${this.type}"></use>
    </svg>
    <span class="visually-hidden">${this.type}:</span>
    ${message}
  `;

  this.regionEl.appendChild(note);

  window.setTimeout(() => {
    this.regionEl.removeChild(note)
  }, this.duration);
}

const infoNotifications = new Notifier(  
  'info',
  document.getElementById('notifications'), 
  5000
);

infoNotifications.notify('Heydon666 a rejoint ce groupe.');  

(Note : La chaîne de caractère « type » est utilisée à la fois pour l’ancre SVG et comme texte alternatif à l’icône.)

Mais que se passe-t-il si l’utilisateur manque des notifications ? Aucun problème. Les notifications ne doivent faire référence qu’à des choses qui peuvent être découvertes par ailleurs dans la mise à jour de l’interface.

Quelques exemples : si la notification fait référence à l’arrivée en ligne d’@Heydon666, vous pourrez découvrir qu’il est là parce qu’il figure dans la liste des utilisateurs actifs, ou que son statut est mis à jour. Pour l’exemple des « récompenses », l’interface devrait en garder une trace sur la page du profil de l’utilisateur. C’est tout à fait classique d’y trouver une chronologie des récompenses.

Les récompenses classées chronologiquement.

Conclusion

Grâce cette merveilleuse technique du « tu l’ajoutes, je le prononce » des live regions ARIA, la mise en œuvre d’une notification inclusive ne pourrait guère être plus facile. Il ne nous reste qu’à perfectionner la clarté et la forme de la communication.

La partie du travail la plus importante n’a finalement rien à voir avec la notification elle-même. Tout est dans la structuration et la présentation de la chronologie dans laquelle chaque message de notification viendra s’insérer. Et comme toujours, la structuration du contenu est primordiale, quand bien même nous sommes en présence d’interactions au sein d’une application web en temps réel.

Points de contrôle

Revenir à la liste des composants