Contenus exclusifs et contenus exclus aux lecteurs d'écran

Pour que l'accessibilité fonctionne bien, il est en général souhaitable que le contenu des pages web soit le plus possible « rendu » de la même manière visuellement qu'avec un lecteur d'écran.
Il est malgré tout parfois utile que certains contenus soient exclusifs aux lecteurs d'écran mais effectivement non affichés, tandis que, au contraire, certains éléments bien affichés ne soient pas rendus lorsqu'on consulte la page avec un lecteur d'écran.

Ce mini-tutoriel va vous expliquer dans quels cas ça peut effectivement être utile, dans quels cas ça ne l'est pas, et comment faire concrètement.

Contenus spécifiquement adressés aux lecteurs d'écran

Les contenus spécifiquement addressés aux lecteurs d'écran sont notamment utiles pour donner des clés de navigation supplémentaires. L'exemple classique est celui d'un titre placé juste avant un menu de navigation.
Rappelons à toutes fins utiles qu'une hiérarchie de titres correcte est un point essentiel pour l'accessibilité. En effet, la grande majorité des utilisateurs de lecteurs d'écran emploient la hiérarchie de titres pour se repérer et pour naviguer rapidement dans les pages web. Or cela n'est évidemment possible que si celle-ci est correcte.

Un titre de niveau juste avant un menu de navigation important est donc un élément stratégique qui permet aux utilisateurs de lecteurs d'écran d'atteindre rapidement le menu en question.

IL existe d'autres moyens pour naviguer rapidement aux endroits clés d'une page comme un menu de navigation, notamment les repères (landmarks);. Mais selon la plupart des statistiques, la navigation par titre reste de loin celle la plus utilisée aujourd'hui, pour au moins deux raisons :

Un autre phénomène récent qui joue en défaveur des landmarks peut aussi être au contraire leur surutilisation sur certains sites, notamment ceux qui abusent des éléments <section> ou <article> sans savoir qu'ils introduisent des lamdmarks implicites (ce n'est apparament pas la plus brillante des idées, d'ailleurs). Quand il y en a trop, c'est comme quand il n'y en a pas, on ne s'y retrouve plus.

On va donc ajouter un titre juste avant notre menu de navigation, en plus d'un repère :

<nav role="navigation">
<h2>Menu principal</h2>
<ul>
<li><a href="#">Accueil</a></li>
<li><a href="#">Produits</a></li>
<li><a href="#">Notre société</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>

Le problème arrive maintenant: comme nous l'avons vu, ce titre est important pour les lecteurs d'écran. Mais, graphiquement, le texte « Menu principal » qui apparaît en gros peut être plus ou moins laid, en plus de montrer une évidence.
En effet, en règle générale, il n'y a pas besoin de cette indication pour voir visuellement que ce qui est juste en-dessous est un menu de navigation. Si le site est graphiquement bien conçu, ça se voit tout de suite ! ET tant mieux puisque c'est le plus souvent ce qu'on veut: que la navigation soit rapidement repérée pour que l'utilisation du site paraisse facile.

L'autre exemple type est un champ de formulaire de recherche, pour lequel le label « Rechercher » est obligatoire du point de vue du WCAG, mais visuellement inutile car on a l'habitude de bien marquer et de retrouver assez vite les formulaires de recherche :

<form action="search.php" method="post">
<p><label for="search">Rechercher: </label>
<input type="search" id="search" placeholder="Entrez vos mots-clés de recherche ici" />
<input type="submit" value="Go!" />
</p>
</form>

Ici aussi, certain graphistes préfèreraient ne pas voir le mot « Rechercher » émanant du label, quand bien même il est absolument indispensable pour les lecteurs d'écran, pour qu'ils sachent ce dont il s'agit sans que celui-ci ne soit obligé de faire des suppositions le plus souvent foireuses.

Alors, comment concilier les deux mondes ? Comment conserver ce qui est utile pour un lecteur d'écran, tout en ne montrant pas inutilement l'évidence pour les autres ?

Des vraies fausses bonnes manières de proposer des contenus exclusifs aux lecteurs d'écran

Du côté CSS, il existe au moins 36 façons de faire disparaître du texte de la zone d'affichage, dont environ 35 sont mauvaises ! On va d'abord montrer ce qu'il ne faut pas faire pour finalement terminer par la bonne solution. Si vous n'avez pas de temps à perdre ou si les histoires ne vous intéressent pas, vous pouvez passer directement au dernier titre de ce sous-chapitre.

display:none

C'est encore régulièrement la première réponse que l'on trouve quand on cherche à masquer du texte tout en le rendant pour les lecteurs d'écran, car elle est on ne peut plus simple. Mais selon la définition du W3C, display:none masque le contenu dans tous les contextes de rendu y compris les lecteurs d'écran !
Tous les lecteurs d'écran à ce jour obéissent à la recommandation du W3C et donc ne rendent pas le contenu stylé en display:none. Ce n'est donc pas la bonne solution.

visibility:hidden

La différence entre visibility:hidden et display:none, c'est que, la zone dédiée à l'affichage est conservée dans le premier cas tandis que pas dans le second, et on a recours à un terme qui évoque sans conteste le sens de la vue. Ce serait donc déjà « plus juste ».
Par contre attendez, il y a un piège: personne n'a jamais réellement définini ce qu'était la « visibilité ». Pour un affichage sur un écran, c'est clair: ça se voit, ou ça ne se voit pas. Mais il y a un mais.

IL faut savoir qu'une bonne partie des lecteurs d'écran créent ce qu'on appelle un « affichage virtuel ». LE contenu de la page est analysé, puis un rendu uniquement textuel plus ou moins linéaire est créé, à l'image d'une cassette audio sur laquelle serait enregistré le texte de la page lu par quelqu'un. C'est dans cet affichage virtuel qu'on se déplace et qu'on peut percevoir le contenu de la page.

Vous voyez sans doute où on en vient: on parle bien d'affichage, ce n'est pas un terme volontairement employé pour troubler. Et, par ailleurs, le terme « lecteur d'écran » veut bien dire ce qu'il veut dire: le dispositif est censé lire ce qui se trouve à l'écran. En toute logique et par extension, donc, ce qui n'est pas effectivement rendu à l'écran ne devrait pas être lu. ET c'est effectivement ce qui se passe avec tous les lecteurs d'écran actuels lorsqu'ils rencontrent un élément stylé en visibility:hidden: il n'est pas lu. Ce n'est donc pas la bonne solution !

Taille, indentation et marges

On s'approche gentiment de la vérité, mais on n'y est pas encore. Dans cette famille de solutions, on trouve des choses comme text-indent:-10000px; ou encore margin-top:100%; ou le pllus simple width:0; et/ou height:0;

Vous vous souvenez de ce qu'on a dit tout à l'heure: ce qui n'est pas à l'écran n'est pas censé être lu. Eh bien, ça s'applique ici, mais pour certains lecteurs d'écran seulement.
En fait, il se trouve que certains logiciels sont plus proches de ce crédo que d'autres. Si Jaws et NVDA sous Windows ne verront aucun inconvénient à une zone de dimensions nulle ou des marges ou espacements anormalement élevées ou négatives, en revanche, apple et son lecteur Voice Over est beaucoup plus pointilleux sur ce point. IL est beaucoup plus proche du visuel perçu et sait très bien détecter que le texte est hors de l'écran dans ces cas de figure.
La conséquence est perverse: le texte est bien lu comme désiré avec NVDA et Jaws sous Windows, mais pas nécessairement avec Voice Over sous Mac OS ou iOS, qui classera soit le texte comme « inprononçable », soit le retirera purement et simplement du rendu. Donc, une fois de plus, ce n'est pas la bonne solution !

Police, couleurs et compagnie

Décidément, l'inventivité pour gruger les lecteurs d'écran et leur détection plus ou moins imparfaite de ce qui est réellement visible ou non est à son comble. Certains ont eu l'idée de mettre des taills de police négatives, d'autres fondent la couleur du texte et de l'arrière-plan, d'autres encore expérimentent la transparence totale via opacity:100%; ou RGBA(X,X,X,1).
Aucune de ces solutions ne marche vraiment dans tous les cas. En plus, il semblerait que, d'après les dires de certains experts du SEO, quelques moteurs de recherche majeurs qualifieraient ces techniques de dopage pour camoufler des mots-clés. Encore une fois, donc, cette solution n'est pas à recommander.

Positionnement

Certains auront tendance à dire « tout ça pour ça ! », mais nos y voilà. Vous êtes des experts CSS et vous savez que le positionnement est quelque chose de complexe. Apparament, trop complexe pour les lecteurs d'écran qui ne peuvent pas facilement détecter ce qui est hors de vue.
Tout ça pour en arriver finalement à ce qui est cité comme étant la recommandation officielle d'Apple. Rien n'est moins sûr sur le ton officiel ou non de ce qui a été trouvé, mais ceci fonctionne avec tous les lecteurs d'écran à l'heure où ces lignes sont écrites :

{
position: absolute;
left: -2px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}

Quelques explications s'imposent :

La même source, que j'ai évidemment perdue entre-temps, propose de ne pas donner de position négative à top pour éviter que, au cas où un élément compris dans la zone invisible était focusable, qu'il ne provoque pas un brusque défilement vers le haut ou un bug d'affichage. Mettre un élément focusable dans une zone invisible est plutôt maladroit, surtout si c'est des liens d'évitement, qui, rappelons-le au passage, ne sont pas particulièrement destinés aux lecteurs d'écran uniquement. Difficile de voir en quoi un élément focusable en pareil endroit pourrait être utile, mais bon, mieux vaut prendre ses précautions jusqu'au bout.

Masquer un contenu inutile aux lecteurs d'écran

Nous voilà maintenant dans l'autre versant de ce mini-tutoriel. Cette fois-ci, on va faire l'inverse: faire en sorte qu'un contenu soit visible à l'affichage, mais invisible pour un lecteur d'écran.

Contrairement à précédemment, il n'y a pas d'exemple type d'application maintes fois évoqué et régulièrement répété ici, ou, du moins, pas encore. Il faut dire que le cas de figure se justifie beaucoup moins souvent aussi.
En plus, il faut être très prudent avec cette possibilité: elle peut être utile pour les contenus qui sont dans le code HTML par la force des choses, mais qui sont en fait purement présentationnels. IL faut être très attentif au fait que :

En ce qui concerne le premier point, on recommande, dans la mesure du possible, de reléguer dans la feuille CSS tout ce qui est du ressort de la présentation uniquement. Par exemple, préférer une image CSS plutôt que <img alt=""> si le alt doit être vide, sauf si l'élément est interactif (auquel cas un alt vide est un non-sens, mais passons).
De même, on devrait préférer des attributs spécifique comme un alt vide, qui sont plus appropriés, plutôt qu'utiliser notre astuce.

Quant au deuxième point, on va y revenir avec un exemple concret plus loin.

Le vrai faux contenu CSS

CSS2 n'a pas apporté que des bonnes choses, et CSS3 ne fait parfois pas mieux. Une propriété qui n'aurait jamais dû exister est Content. Celle-ci permet, dans certaines mesures, d'ajouter automatiquement du texte au début ou à la fin d'un élément, sans qu'il soit présent dans le code HTML. Par exemple :

<p id="test">Hello, world !</p>
#test:before { Content: "It works !"; }

Le texte généré par cette propriété, est-il du contenu, ou de la présentation ? Vaste question, qui n'a pas de réponse tranchée. On se contentera d'un laconique « ça dépend », n'en déplaise à certains.

Vous vous souvenez de ce qu'on a déjà dit tout à l'heure: ce qui ne se voit pas à l'écran n'est pas censé être lu. Ici, on va appliquer le contraire: tout ce qui est visible est censé être lu.
Eh bien, de nouveau, certains lecteurs d'écran sont plus proches de cette affirmation que d'autres. Jaws a décidé de considérer le contenu généré par la propriété Content comme étant de la présentation pure, et ne le lira jamais. NVDA pour sa part, se range du même côté qu'Apple et lira le contenu comme s'il avait été présent dans le code HTML.
Aucune des deux visions ne peut être considérée comme fausse: d'un côté, on peut dire que puisque c'est du CSS, c'est de la présentation. De l'autre, on peut dire que puisque c'est affiché à l'écran, ça doit être lu. Tout le monde a raison !

Si votre objectif était, par le biais de Content, d'afficher du contenu textuel qui ne soit pas rendu par les lecteurs d'écran, c'est donc raté !
On va y venir, à pourquoi ça peut être utile parfois, et pourquoi ça peut être parfois la pire des idées imaginables.

Quand la limite entre présentation et contenu devient floue

Avant de continuer, revenons à une raison qui a poussé les concepteurs de CSS2 à introduire cette infâme propriété Content: l'ajout des compteurs CSS.

L'exemple le plus concret et le plus disputé des compteurs CSS est certainement celui des listes numérotés, mais sachez qu'on peut aussi très bien l'utiliser pour numéroter des tableaux, des figures, ou d'autres contenus.

En HTML4 et plus encore en XHTML 1.0, on voyait les attributs type et start de la balise <ol> rendus dépréciés, de même que l'attribut value de <li>. Ils ont été réintroduits en HTML5 et c'est une bonne chose.
En XHTML 1.0, donc, pour faire les choses bien, si on voulait commencer une liste numérotée à 10 au lieu de 1, si on voulait numéroter de 10 en 10, ou si on voulait compter A, B, C au lieu de 1, 2, 3, il fallait le faire complètement en CSS, avec les compteurs, et en utilisant la propriété Content pour afficher la valeur du compteur.

Pourquoi est-ce un problème ? Eh bien, imaginez qu'un lecteur d'écran ignore complètement la propriété Content (c'est le cas de Jaws), et que vous devez répondre à une question comme celle-ci, avec un style adéquat utilisant Content et les compteurs (il y a plus simple pour ce petit exemple, avec list-style-type évidemment, mais passons) pour que les réponses soient, du point de vue de l'affichage, effectivement numérotées A, B, C au lieu de 1, 2, 3 :

<p>Choisissez une réponse A, B ou C</p>
<ol>
<li>Réponse A</li>
<li>Réponse B</li>
<li>Réponse C</li>
</ol>
<p>Si vous avez répondu A, vous êtes quelqu'un de courageux</p>
<p>Si vous avez répondu B, vous êtes quelqu'un de généreux</p>
<p>Si vous avez répondu C, vous êtes plutôt égoïste</p>
<p>Et si vous avez répondu D, vous êtes définitivement un abruti étant donné qu'il n'y a pas de réponse D.</p>

Si on a supprimé la numérotation classique avec list-style-type:none, cela est bien pris en compte par jaws, il n'y a donc plus de numérotation du tout. Si on ne l'a pas fait, la numérotation par défaut est toujours 1, 2, 3.
Au final, on me demande de choisir entre A, B, C et je n'ai que 1, 2, 3, ou voire même rien du tout ! Je fais quoi moi ?
Et pendant ce temps, l'utilisateur de NVDA n'y verra aucun problème . . .

Évidemment, utilisateur de lecteur d'écran ne veut pas dire abruti, et pour cet exemple simple, on a vite fait de comprendre que 1 correspond à A, 2 à B et 3 à C. Mais dans la vraie vie, il y a des choses bien plus compliquées que celles-là ! C'était juste un exemple très simple pour montrer l'idée.

Autre exemple problématique: si on numérote des figures ou des tableaux avec des compteurs CSS et qu'on y fait référence en toutes lettres dans le texte, on a vite fait de ne plus rien y comprendre, ou de ne pas retrouver ce qu'on cherche.

Voilà donc un exemple où la numérotation n'est pas un artifice de présentation ne portant pas de sémantique. Pour ce genre de chose, c'est une très mauvaise idée de vouloir masquer des chiffres aux lecteurs d'écran, car elle véhicule clairement un sens nécessaire à la compréhension.

Et alors, quand est-ce que masquer du contenu uniquement aux lecteurs d'écran peut être utile ?

Parce que les choses sont compliqués et subjectives, et surtout dans l'accessibilité, voici maintenant un exemple où c'est tout le contraire: une numérotation totalement inutile aux lecteurs d'écran.

Je ne vous cache pas que l'idée de cet article me vient d'une questiont au départ plutôt anodine posée sur un forum où je me rends compte que numéroter des lignes pour un code source est une affaire plus compliqué qu'il n'y paraît du point de vue de l'accessibilité. Sur une majorité de sites que je consulte régulièrement, je m'aperçois que c'est la deuxième proposition évoquée dans le post qui est le plus souvent choisie, et ça se comprend car elle n'a pas l'inconvénient de gêner le copier-coller. L'idée de base est la suivante :

<div>
1<br />
2<br />
3<br />
4<br />
5< br/>
</div>
<pre><code>
#include<stdio.h><br />
int main (void) {<br />
printf("Hello, world !");<br />
return 0;<br />
}<br />
</code></pre>

Rappelez-vous qu'avec un lecteur d'écran, le contenu est lu linéairement dans l'ordre du code HTML. En d'autres termes, on obtient d'abord tous les numéros, et ensuite tout le code. En l'état, non seulement ces numéros ne sont d'aucune utilité, mais en plus ils gênent et alourdissent la lecture.

ON pourrait s'en passer, alors ? La réponse est oui. Dans ce cas, ça peut vraiment être utile.

La réponse tient en moins d'une ligne: l'attribut aria-hidden indique aux lecteurs d'écran que le contenu de l'élément est caché visuellement. IL peut prendre la valeur true ou false.
Comme nous l'avons vu, les lecteurs d'écran d'aujourd'hui sont assez intelligents pour remarquer tout seuls qu'un contenu est caché, notamment ceux avec display:none et/ou visibility.Hidden. Cet attribut aria-hidden a été au départ conçu au cas ou un masquage ne serait pas remarqué.
Pratiquement personne ne s'en préoccupe, puisque display:none fonctionne, tout simplement, et qu'il n'y a pas de raison de supprimer un contenu par un procédé exotique tout en le conservant pour les lecteurs d'écran, sauf cas très contrôlé comme ceux exposés en première partie.

Sauf que, pour le coup, aria-hidden="true" a un effet qui nous est utile ici: tous les lecteurs d'écran qui comprennent ARIA suppriment complètement l'élément concerné de leur affichage virtuel, sans poser de question. Utile pour faire ce qu'on voulait faire, c'est-à-dire qu'un contenu soit visuellement affiché sans qu'il ne soit lu par les lecteurs d'écran.

Conclusion

Un article qui était prévu pour être une petite astuce tout au début, et qui devient finalement quelque chose de relativement long. Encore une fois, vous vous exclamerez peut-être « tout ça pour ça ! ».
Certes ce sont des choses extrêmement spécifiques, mais j'espère qu'elles vous ont appris quelque chose et qu'elles pourront vous servir. Ce qu'il faut retenir, c'est que ces petites astuces peuvent être utiles, mais qu'il ne faut pas en abuser. Dans tous les cas, on reste dans quelque chose de très complexe et de très précis, et donc, il faut toujours rester très prudent sur comment et pourquoi on le fait.

Commentaires

1. olive, 29.10.2013 22:12:55

Waou ! Je rejoins un commentaire qui avait été fait sur le billet précédent. Tu devrais proposer des formations à l'accessibilité du web. Tu maîtrise le sujet c'ets indéniable. Je ne suis pas franchement débutant en développement web, et connais bien les problématiques d'accessibilité, mais j'ai presque tout appris dans ton article. Bravo !

Bref, c'est décidé, j'ajoute le flux RSS de ton site à la liste de ma veille technologique quotidienne.

Olivier

2. QuentinC, 30.10.2013 09:17:30

Merci pour ton commentaire, ça me fait plaisir ! Par contre je ne suis pas professionnel, et encore moins expert en la matière. Je suis juste un étudiant en informatique moi-même très concerné par l'accessibilité à l'information et je me bats tout le temps pour obtenir ce que je ne peux pas lire par la voie normale. Je n'ai pas vraiment le temps de former des gens, je n'ai pas (encore) légalement les qualifications pour, en plus de ne certainement pas avoir la patience nécessaire.

Pour information, si tu n'es intéressé que par l'accessibilité, tu peux t'abonner au RSS que pour les articles qui contiennent ce mot-clé. Tu as dû t'apercevoir que je vais un peu dans tous les sens et que les sujets que j'aborde sont très divers...

Commenter