La Cascade

Un peu de tout sur CSS, HTML, SVG et JS,traduit du web anglophone
Rechercher

Guide de l'accessibilité du clavier: HTML et CSS (1ère partie)

par Cristian Diaz, 19 novembre 2022, css, html, accessibilite, semantique, article original paru le 14 novembre 2022 dans Smashing Magazine

Comment utiliser HTML et CSS pour créer une expérience accessible pour les utilisateurs de claviers?


L'accessibilité du clavier est un élément important de l'expérience utilisateur. Les directives d'accessibilité aux contenus Web (WCAG) contiennent de nombreux critères à ce sujet. Pourtant, il est quelque peu négligé, ce qui affecte l'expérience de nombreux utilisateurs, principalement les personnes souffrant de handicaps moteurs — toute condition qui limite les mouvements ou la coordination.

Certaines conditions telles qu'un bras cassé, la perte ou l'endommagement d'un membre, la dystrophie musculaire, l'arthrite et d'autres peuvent rendre impossible l'utilisation d'une souris pour naviguer sur un site. Par conséquent, rendre un site navigable au moyen du clavier est un élément très important pour garantir l'accessibilité et la convivialité de nos sites Web.

L'importance de rendre un site accessible aux utilisateurs souffrant de handicaps moteurs devient encore plus évidente lorsque vous apprenez qu'ils ont accès à davantage d'options technologiques d'assistance. Les claviers ne sont même pas le point central de l'assistance aux handicapés moteurs ! Il existe des outils comme les commutateurs que vous utilisez avec votre main (ou même avec votre tête) pour travailler avec n'importe quel appareil, ce qui aide beaucoup les personnes souffrant de handicaps moteurs plus graves. Vous pouvez voir comment ces technologies fonctionnent dans cette démonstration faite par Rob Dodson ou dans cette vidéo de Christopher Hills.

Dans cet article, je vais vous expliquer comment utiliser HTML et CSS pour créer une expérience accessible pour les utilisateurs de claviers, et je listerai les critères WCAG que nous devons prendre en considération.

HTML

L'une des bases de la création d'un site Web accessible pour les utilisateurs de clavier est de savoir quels éléments doivent être navigables au clavier. Pour cela, une bonne sémantique HTML est cruciale car elle indiquera le type d'éléments sur lesquels nous voulons nous concentrer avec la navigation au clavier.

Les bases

Lorsqu'un utilisateur appuie sur la touche Tab, il peut sélectionner l'élément suivant dans le code HTML, et lorsqu'il appuie sur les touches Shift + Tab, il peut accéder au dernier élément. Ceci étant dit, quels éléments doivent être focalisables ? Réponse : tout ce qui nécessite une interaction avec l'utilisateur ! Vous devez pouvoir trouver, entre autres, les éléments button, a, input, summary, textarea, select, et les contrôles des éléments audio, et video (lorsque vous leur ajoutez l'attribut controls). En outre, certains attributs peuvent rendre un élément navigable au clavier, comme contenteditable ou tabindex. Dans le cas de Firefox, toute zone comportant un défilement sera également accessible au clavier.

En plus de cela, vous devez pouvoir :

  • Activer les éléments `button`, `select`, `summary` et `a` à l'aide de la touche `Entrée`. N'oubliez pas qu'à l'exception de l'élément `a`, vous pouvez également les activer avec la touche `Espace`.
  • Utiliser les touches fléchées pour naviguer entre les différentes `input` avec le type `radio` si elles partagent le même attribut `name`.
  • Cocher ces entrées à l'aide de la touche `Espace` (n'oubliez pas que lorsque vous naviguez avec les touches flèches, les `input` radio sont cochés dès que le clavier est activé, mais que cela ne se produit pas avec les `input` de type case à cocher).
  • Utiliser les touches flèche-vers-le-haut et flèche-vers-le-bas pour naviguer entre les différentes options d'un élément `select`.
  • Ferme la liste affichée de l'élément `select` et les diverses fenêtres contextuelles d'`input`.
  • Utiliser les touches flèches pour faire défiler verticalement ou horizontalement un document.

Il existe probablement d'autres interactions, dont certaines dépendent des différences entre les systèmes d'exploitation et les navigateurs, mais ce que nous avons vu couvre l'essentiel de ce que vous pouvez faire avec le clavier.

Cela signifie-t-il que ces éléments sont automatiquement accessibles au clavier par défaut ? Pas tout à fait. Une bonne structure HTML est très utile, elle rend l'essentiel du contenu accessible par défaut, mais vous devez quand même couvrir certains problèmes.

Par exemple, certains types d'input comme date, datetime-local, week, time et month ont des popups qui peuvent fonctionner différemment selon les navigateurs. Chrome, par exemple, vous permet d'ouvrir le popup du sélecteur de date (date picker) en appuyant sur la touche Entrée ou Espace dans un bouton dédié dans la saisie. Cependant, avec Firefox, vous devez appuyer sur la touche Entrée (ou Espace) dans les champs du jour, du mois ou de l'année pour ouvrir la fenêtre contextuelle et modifier chaque champ à partir de là.

Ce manque de cohérence peut être un peu rebutant, et c'est peut-être juste une question de préférence personnelle. Toujours est-il que j'ai l'impression que l'expérience Firefox n'est pas très intuitive, ce qui amène à penser que, sans doute, l'une de ces expériences est plus accessible au clavier que l'autre. Donc, si vous voulez créer une bonne expérience clavier, accessible et cohérente entre les navigateurs, il vous faudra plus que du HTML pour cela. Si vous voulez essayer vous-même, consultez cette compilation (en français) de types d'entrée par MDN et naviguez par vous-même.

En plus du point précédent, certains composants exigent que les éléments soient focalisables au clavier sans être nativement sélectionnables. Dans d'autres cas, nous devons gérer le focus clavier manuellement, et notre balisage doit nous aider à le faire. Dans les deux cas, nous devrons utiliser un attribut HTML qui nous aidera dans cette tâche.

Attribut tabindex

Cet attribut nous aidera à amener l'accessibilité clavier à des niveaux de configuration plus fins. Il prend un nombre entier, et son utilisation correcte nous aidera à rendre un élément DOM accessible au clavier. Avec tabindex, nous pouvons trouver trois cas différents :

tabindex="0"

Il fait en sorte que l'élément soit focalisable par le clavier. En général, vous ne souhaitez pas ajouter le focus clavier à un élément, sauf s'il n'est pas interactif, mais certains scénarios l'exigent.

L'un d'eux est lorsque vous avez un composant avec un défilement à côté de l'élément body. Sinon, les utilisateurs du clavier ne pourront pas voir le contenu dans toute son étendue. Parmi les composants susceptibles d'avoir ce problème, citons les carrousels avec défilement, les tables et les extraits de code. Pour donner un exemple, tout extrait de code créé à l'aide de prism.js possède l'attribut tabindex="0". Ouvrez le site de prism.js et naviguez-y à l'aide de la touche Tab. Vous pourrez avoir un focus sur les snippets et contrôler le défilement vertical et horizontal à l'aide des touches flèches.

Copie d'écran de prismjs.com focalisé par le clavier. Un contour noir entoure l'élément, indiquant qu'il est en focus.
Un contour noir entoure l'élément, indiquant qu'il est en focus.

Certaines personnes qui s'initient à l'accessibilité du Web pensent que c'est une bonne idée d'ajouter l'attribut tabindex="0" à chaque élément car elles pensent que cela aidera les utilisateurs de lecteurs d'écran à naviguer facilement sur un site. Il s'agit d'une pratique terrible pour deux raisons :

  1. Les utilisateurs de lecteurs d'écran ont plusieurs façons de naviguer sur un site. Ils peuvent sauter entre les titres, les balises de repère (telles que main, nav, ou aside) ou les éléments de formulaire, et ils n'ont pas besoin de cette aide supplémentaire pour créer un site accessible, tant que le balisage est approprié.
  2. Cela peut rendre la navigation au clavier difficile car un utilisateur devra appuyer plusieurs fois sur la touche Tab pour arriver au contenu souhaité, et pour certains handicaps moteurs, le fait d'avoir trop d'éléments focalisables peut créer une expérience physiquement pénible.

Donc, pour résumer : c'est une technique utile pour certains éléments, mais la plupart du temps, vous vous en sortirez très bien si vous ne l'utilisez pas, et en tout cas, vous ne devez pas l'utiliser dans chaque élément de votre site.

Tabindex négatif

Avant de commencer, nous devons garder à l'esprit deux concepts : un élément DOM est à la fois focalisable (c'est-à-dire que vous pouvez le focaliser de manière programmatique avec JavaScript) et tabulable (c'est-à-dire qu'il peut être sélectionné avec la touche Tab).

En gardant cela à l'esprit, c'est ici que le tabindex négatif entre en jeu car il le retire de l'arbre d'accessibilité, il ne peut plus être tabulé, (mais vous pouvez toujours le focaliser avec JavaScript). C'est important pour des composants spécifiques car, dans certains cas, nous devons faire en sorte qu'un élément normalement tabulable ne puisse pas être tabulé, ou qu'un élément soit focalisable mais pas tabulable.

Les onglets en sont un exemple. Un modèle recommandé pour ce composant est de s'assurer que lorsque vous appuyez sur la touche Tab quand vous êtes situé sur l'onglet actif, cela nous amène au tabpanel actif plutôt que mettre le focus sur l'onglet suivant. Nous pouvons y parvenir en ajoutant un tabindex négatif à tous les onglets non actifs comme ceci :

<ul role="tablist">
  <li role="presentation">
    <button role="tab" href="#panel1" id="tab1" aria-selected="true">
      Tab one
    </button>
  </li>
  <li role="presentation">
    <button role="tab" href="#panel2" id="tab2" tabindex="-1">
      Tab two
    </button>
  </li>
  <li role="presentation">
    <button role="tab" href="#panel3" id="tab3" tabindex="-1">
      Tab three
    </button>
  </li>
  <li role="presentation">
    <button role="tab" href="#panel4" id="tab4" tabindex="-1">
      Tab four
    </button>
  </li>
</ul>

Nous verrons plus tard d'autres exemples sur la façon dont un tabindex négatif nous aidera à avoir plus de contrôle sur la gestion de l'état du focus dans différents composants, mais gardez à l'esprit qu'un tabindex négatif sera important dans ces cas.

Enfin, vous pouvez mettre n'importe quel nombre entier négatif dans la propriété tabindex, et cela fonctionnera de la même manière. tabindex="-1" et tabindex="-1000" ne feront aucune différence, mais par convention, j'ai tendance à utiliser -1 lorsque nous utilisons cet attribut.

Tabindex positif

Un tabindex positif rendra l'élément focalisable par le clavier, mais l'ordre sera défini en fonction de l'entier utilisé. Cela signifie que le clavier parcourra d'abord tous les éléments avec l'attribut tabindex="1", puis ceux avec tabindex="2", et après avoir parcouru tous les éléments avec un tabindex positif, il prendra en compte tous les éléments interactifs par défaut et ceux avec l'attribut tabindex="0". C'est ce que l'on appelle le scope de navigation du focus ordonné par tabindex.

Maintenant, c'est une configuration que vous ne devriez pas utiliser. Il est préférable de placer les éléments focalisables requis dans votre site dans l'ordre nécessaire. Sinon, vous pourriez créer une expérience très déroutante pour les utilisateurs du clavier, ce qui constituerait un échec du critère 2.4.3 des WCAG : Ordre de focalisation.

Si une page Web peut être parcourue de manière séquentielle et que les séquences de navigation affectent le sens ou le fonctionnement, les composants focalisables reçoivent la focalisation dans un ordre qui préserve le sens et le fonctionnement.

Critère de réussite 3.2.1: Ordre de focalisation

Cela pourrait être utile si vous voulez que les utilisateurs du clavier se concentrent sur les widgets avant d'atteindre le contenu de la page, mais cela serait un peu déroutant pour les utilisateurs de technologies d'assistance (comme les lecteurs d'écran). Donc, encore une fois, vous feriez mieux de créer un ordre logique dans le DOM.

Attribut inerte

Je dois noter rapidement un attribut entrant qui nous aidera beaucoup avec l'accessibilité du clavier, appelé inert. Cet attribut rendra le contenu inaccessible par les technologies d'assistance.

Bon, vous vous demandez peut-être comment il peut être utile que quelque chose supprime l'accessibilité du clavier, mais dans certains cas, c'est une bonne chose ! Un composant qui en bénéficiera est celui des modales. En ajoutant cet attribut à tous les éléments du site, à l'exception de cette modale, il sera facile de créer un "piège à focus". Ainsi, vous vous assurerez que l'utilisateur ne peut pas naviguer accidentellement vers d'autres parties du site à l'aide de la touche Tab, à moins qu'il ne ferme cette modale. Pour l'instant, la création d'un piège à clavier nécessite une grosse réflexion avec JavaScript (je vous expliquerai comment dans la deuxième partie de ce guide). Donc, avoir un moyen de rendre la chose plus facile avec cet attribut sera bien pratique.

Ça paraît plutôt cool, non ? Eh bien, malheureusement, l'utilisation de cet attribut n'est pas encore recommandée. Si vous consultez la page de caniuse.com sur cet attribut, vous remarquerez qu'il est très récent ; Opera ne le prend pas encore en charge. L'implémentation la plus récente de cet attribut est la version 105 de Firefox, et au moment de la rédaction de cet article, il s'agit d'une version bêta ! Il est donc encore très tôt pour le faire. Il existe un polyfill pour l'attribut inert, mais pour l'instant, il est un peu coûteux en termes de performances. Je vous suggère donc sérieusement de ne pas l'utiliser maintenant pour la production. Mais une fois que nous aurons un support adéquat pour cet attribut, certains modèles de composants seront plus faciles à créer.

CSS

CSS est un outil essentiel pour l'accessibilité du clavier car il nous permet de créer un niveau de personnalisation de l'expérience, ce qui est important pour la conformité aux critères WCAG 2.2. De plus, CSS possède de multiples sélecteurs qui aideront à créer une bonne expérience clavier, mais attention car une mauvaise utilisation de certaines propriétés peut être contre-productive. Plongeons dans l'utilisation de CSS pour créer une expérience accessible aux utilisateurs de clavier.

Indicateur de focus

Lorsque vous utilisez une souris, vous pouvez voir avec quel élément vous pouvez interagir grâce au curseur, et vous ne voudriez pas retirer le curseur à votre utilisateur, n'est-ce pas ? Cela le rendrait incapable de savoir quel élément il veut utiliser !

Nous avons un concept similaire pour la navigation au clavier, et il s'appelle un indicateur de focus, qui par défaut est un contour qui entoure un élément focalisable par le clavier lorsqu'il est sélectionné par celui-ci. Il est essentiel de s'assurer que tous vos éléments accessibles au clavier disposent d'un indicateur de focus. C'est une condition importante pour rendre un site Web accessible au clavier, selon les critères WCAG :

Toute interface utilisateur utilisable au clavier possède un mode de fonctionnement où l'indicateur de focus clavier est visible.

Critère de réussite 2.4.7 : Focus visible

Le style de focus est différent selon le navigateur que vous utilisez. Vous pouvez voir comment il se présente dans les différents navigateurs dans ces images par défaut et lorsque vous utilisez la propriété CSS color-scheme réglée sur dark, juste pour vérifier comment les styles par défaut se comporteraient en mode sombre.

Contour noir sur fond blanc, et blanc sur fond noir
Indicateur de focus de Chrome.
Contour bleu, quel que soit le fond
Indicateur de focus de Firefox.
Contour bleu sur fond blanc, gris sur fond noir
Indicateur de focus de Safari.

Comme vous pouvez le remarquer, les navigateurs basés sur Chromium comme Chrome ou Edge ont un contour noir et blanc, qui fonctionne en mode clair et foncé. Firefox a opté pour un contour bleu qui se remarque dans les deux modes. Et Safari (et les navigateurs basés sur Webkit, car à l'heure actuelle, tous les navigateurs iOS utilisent Webkit comme moteur de navigation) a presque le même aspect que Firefox, mais avec un contour encore plus subtil pour un schéma de couleurs sombres.

Critère 2.4.11 des WCAG #.

Maintenant, les indicateurs de focus par défaut sont visibles, mais sont-ils suffisants ? La réponse est "non". Même si ça peut fonctionner dans certains cas, les personnes souffrant de déficiences visuelles auront du mal à le remarquer. Les WCAG ont donc créé le critère de réussite 2.4.11 - Apparence de focus pour rendre un indicateur de focus accessible. Pour l'instant, ce critère fait partie des WCAG 2.2, qui sont une recommandation candidate. Il est donc peu probable qu'il soit modifié avant la version finale, mais gardez à l'esprit qu'il est toujours susceptible d'être modifié.

Lorsque l'indicateur de focus clavier est visible, l'une des deux conditions suivantes, ou les deux, sont remplies :

  • L'indicateur de focus :
    • entoure la présentation visuelle du composant de l'interface utilisateur, et
    • présente un rapport de contraste d'au moins 3:1 entre les mêmes pixels dans les états focalisé et non focalisé,et
    • présente un rapport de contraste d'au moins 3:1 par rapport aux couleurs adjacentes.
  • Une zone de l'indicateur de focus répond à tous les critères suivants :
    • est au moins aussi grande que la zone d'un périmètre de 1 pixel CSS d'épaisseur du composant non focalisé, ou est au moins aussi grande qu'une ligne de 4 pixels CSS d'épaisseur le long du côté le plus court de la boîte de délimitation minimale du composant non focalisé, et
    • présente un rapport de contraste d'au moins 3:1 entre les mêmes pixels dans les états focalisé et non focalisé, et
    • présente un rapport de contraste d'au moins 3:1 entre les couleurs adjacentes de l'indicateur non focalisé, ou n'est pas plus mince que 2 pixels CSS.
critère de réussite 2.4.11 - Apparence de focus

Il y a quelque chose d'important à considérer ici, et c'est la zone de l'indicateur de focus. Cette zone doit répondre aux exigences de contraste de ce critère. Pour illustrer cela, je vais utiliser un exemple que Sara Soueidan a réalisé pour son article "A guide to designing accessible, WCAG-compliant focus indicators".

Illustration avec 3 boutons : le premier est bleu avec un label blanc, dans son état par défaut, sans focus. le deuxième est le même bouton avec un contour noir épais et la légende 'focalisé'. Le dernier est le même bouton mais avec un motif appliqué au contour, indiquant que cette zone avec motif est la zone contrastée

Cet exemple utilise un contour, mais n'oubliez pas que vous pouvez utiliser d'autres propriétés pour déterminer l'état du focus, comme la couleur d'arrière-plan ou des façons créatives d'utiliser le box-shadow, tant que cela est conforme aux exigences. En tout cas, n'utilisez pas la propriété outline : none pour éliminer le contour de l'élément.

C'est important pour le mode de contraste élevé de Windows, car lorsqu'il est actif, les couleurs de votre site Web seront remplacées par celles choisies par l'utilisateur. Ainsi, dépendre de propriétés telles que background-color n'aura aucun effet à ce niveau. À la place, utilisez la déclaration CSS outline-color : transparent avec l'épaisseur appropriée pour respecter les critères WCAG. Vous pouvez voir des exemples de ce fonctionnement dans mon article sur le mode de contraste élevé de Windows.

La taille optimale des contours

Une façon simple de créer un indicateur de focus conforme est d'utiliser cette méthode que Stephanie Eckles a suggérée dans sa conférence Modern CSS Upgrades To Improve Accessibility. Tout d'abord, nous définissons des propriétés personnalisées dans les éléments interactifs. N'oubliez pas que vous pouvez ajouter d'autres éléments à la règle en fonction de la complexité de votre projet :

/* Ajoutez d'autres selecteurs dans cette règle :is si nécessaire */

:is(a, button, input, textarea, summary) {
  --outline-size: max(2px, 0.08em);
  --outline-style: solid;
  --outline-color: currentColor;
}

Et ensuite, nous utilisons ces propriétés personnalisées pour ajouter une règle de focus global :

:is(a, button, input, textarea, summary):focus {
  contour: var(--outline-size) var(--outline-style) var(--outline-color);
  outline-offset: var(--outline-offset, var(--outline-size));
}

L'utilisation de 0,08em ici permet de donner une taille de contour plus grande si la police est plus grande, ce qui permet de mieux adapter la zone de contraste de l'élément à la taille de la police de l'élément.

Gardez à l'esprit que même si les WCAG mentionnent que la zone de mise au point "est au moins aussi grande que la zone d'un périmètre de 1 pixel CSS d'épaisseur de l'élément non mis au point", elles mentionnent également qu'elle doit avoir "un rapport de contraste d'au moins 3:1 par rapport aux couleurs adjacentes non indicatrices de mise au point, ou n'est pas plus fine que 2 pixels CSS". Ainsi, une épaisseur minimale de 2px est nécessaire pour se conformer aux WCAG.

N'oubliez pas que vous pouvez avoir besoin d'une ligne plus épaisse si vous utilisez un outline-offset négatif, car cela réduira le périmètre du contour. De même, l'utilisation d'un contour pointillé ou en pointillé réduira la zone ciblée de moitié environ, vous devrez donc utiliser une ligne plus épaisse pour compenser.

La zone idéale du contour est liée au périmètre de l'élément. Sara Soueidan a une fois de plus fait un excellent travail en expliquant le fonctionnement de cette formule dans son article sur les indicateurs de focus. Consultez-le si vous voulez mieux comprendre les mathématiques qui se cachent derrière cette question et comment les appliquer.

Sélecteur CSS liés au focus

En CSS, vous utilisez normalement la pseudo-classe :focus pour appliquer un style à un élément lorsqu'il est focalisé par une tabulation clavier, et elle fait bien son travail. Mais les CSS modernes nous ont donné deux nouvelles pseudo-classes, l'une qui nous aide dans un certain cas d'utilisation et l'autre qui résout un problème se produisant lorsque nous utilisons la pseudo-classe :focus. Ces pseudo-classes sont :focus-within et :focus-visible. Voyons ce qu'elles font et comment elles peuvent nous aider à améliorer l'accessibilité du clavier :

:focus-within

Cette pseudo-classe ajoute un style à chaque fois que l'élément est focalisé ou que l'un de ses enfants l'est également. Faisons un exemple rapide pour montrer à quoi cela ressemble :

<form>
  <label for="name">
    Name:
    <input id="name" type="text" />
  </label>
  <label for="email">
    Email:
    <input for="email" type="email" />
  </label>
  <button>Submit</button>
</form>

Note rapide au passage : il serait préférable de ne pas utiliser label pour envelopper l'élément d'input. Ça fonctionne dans tous les navigateurs, mais ça ne fonctionne pas bien avec le logiciel de reconnaissance vocale Dragon car il ne sera pas reconnu de manière correcte.

formulaire {
  display: grid;
  gap: 1em;
}

label {
  affichage: grille;
  gap: 1em;
  padding: 1em;
}

label:focus-within {
  background-color: rebeccapurple;
  couleur: blanc;
}
Un formulaire avec le code précédemment décrit. Le champ 'email' est en focus, et le label a un arrière-plan violet. L'entrée dans le label a le contour par défaut du navigateur

Cette pseudo-classe est intéressante pour enrichir les styles de certains composants, comme montré précédemment, et dans d'autres, elle aide beaucoup à rendre le contenu accessible aux utilisateurs du clavier. Par exemple, j'ai créé une carte pour mon article sur les media queries hover, pointer, any-hover et any-pointer. Cette carte affiche le contenu lorsque l'utilisateur place le curseur dessus, mais elle affiche également le contenu lorsque vous focalisez le bouton à l'intérieur de celle-ci à l'aide de la pseudo-classe :focus-within en utilisant les mêmes règles qui sont déclenchées au survol. Vous pouvez consulter le code dans l'article mentionné ainsi que dans ce CodePen :

:focus-visible

D'autre part, nous avons un comportement assez intéressant avec les styles de focus, en raison de la façon dont le navigateur décide quand appliquer cet état à un élément. Si vous utilisez la pseudo-classe :focus, la plupart des navigateurs considéreront que cliquer sur l'élément revient à le focaliser, ce qui crée un "faux positif" où l'élément semble être focalisé par un clavier alors que ce n'est pas le cas.

Pour résoudre ce problème mineur, nous avons maintenant la pseudo-classe :focus-visible qui crée un état de focalisation si et seulement si l'élément est focalisé par un clavier. Gardez à l'esprit que ce comportement s'appliquera aux éléments comme button ou a et à la plupart des éléments d'input comme checkbox, radio ou submit. Mais les styles de focalisation seront toujours appliqués lorsque vous cliquez sur les éléments comme select, certains input qui reçoivent tout type de texte comme text, number, ou l'élément textarea.

Cela ne se produit plus aujourd'hui car les navigateurs modernes utilisent :focus-visible comme état de focalisation par défaut. Mais n'oubliez pas que vous souhaitez probablement modifier l'indicateur de focus par défaut du navigateur pour être conforme à la norme WCAG 2.4.11. Vous aurez donc besoin de :focus-visible pour éviter ce comportement.

Si vous consultez la page de caniuse.com sur la pseudo-classe :focus-visible, vous remarquerez qu'il est actif dans tous les navigateurs. Mais dans Safari, il est actif depuis une version relativement récente (15.4, qui a été publiée le 13 mars 2022), ce qui signifie que certains utilisateurs n'ont probablement pas encore mis à jour leur navigateur. Par conséquent, nous devrions offrir une sorte de solution de repli si le navigateur ne prend pas en charge cette pseudo-classe. Nous pouvons le faire en utilisant la feature query @supports.

Précédemment, nous avons créé un bon style global pour le style focus, appliquons maintenant la pseudo-classe :focus-visible à cette règle :

@supports selector(:focus-visible) {
  *:focus {
    outline: none;
  }

  *:focus-visible {
    outline: var(--outline-size) var(--outline-style) var(--outline-color);
    outline-offset: var(--outline-offset, var(--outline-size));
  }
}

Remarque rapide : je sais que j'ai indiqué que l'utilisation de la règle outline : none n'était pas une bonne idée, mais comme nous la remplaçons par :focus-visible, il s'agit d'un scénario "acceptable" pour l'utiliser. N'oubliez pas d'utiliser outline même s'il n'est pas visible. Outline est votre ami !

Considérations sur la mise en page

La puissance des CSS modernes pour créer des mises en page est formidable, mais il y a un ensemble de pratiques que nous devrions essayer d'utiliser avec prudence car elles peuvent rendre l'expérience de navigation au clavier problématique.

display : contents

Cette règle est très intéressante. Elle supprime la boîte de l'élément et fait que les enfants de l'élément agissent comme s'ils étaient des enfants directs de l'élément du grand-parent, sans supprimer la sémantique. Elle fait que les enfants d'un élément se comportent comme s'ils étaient ses frères et sœurs. Cela peut sembler un peu confus, je vais donc l'expliquer par un exemple. Supposons que nous ayons le balisage de l'en-tête de ce site :

<header>
  <a href="#">Go to home</a>
  <nav>
    <ul>
      <li>
        <a href="#">Clothes</a>
      </li>
      <li>
        <a href="#">Accessories</a>
      </li>
      <li>
        <a href="#">Shoes</a>
      </li>
    </ul>
  </nav>
</header>

Si nous ajoutions la règle display : contents à l'élément ul, nous supprimerions la boîte sans supprimer la sémantique, ce qui ferait des éléments li les enfants de l'élément parent de ul (dans ce cas, le conteneur nav) comme ceci :

<header>
  <a href="#">Go to home</a>
  <nav>
    <li><a href="#">Clothes</a></li>
    <li>
      <a href="#">Accessories</a>
    </li>
    <li>
      <a href="#">Shoes</a>
    </li>
  </nav>
</header>

Et encore, c'est sans supprimer la sémantique de l'élément parent. Cela apporte quelques possibilités intéressantes pour la création de mises en page, comme l'explique Kevin Powell dans sa vidéo sur cette propriété. Cependant, elle a un comportement avec les éléments interactifs du clavier qu'il faut éviter.

Si vous l'utilisez dans un élément pouvant être focalisé par le clavier, ces éléments ne pourront pas être tabulés. Pour être juste, il est très peu probable que vous vous trouviez dans une situation où vous devez utiliser display : contents dans un élément focalisable par le clavier (le seul cas auquel je puisse penser si vous voulez l'utiliser pour réinitialiser les styles de ces éléments). Et les problèmes d'accessibilité de cette propriété sont pour d'autres raisons plus courantes (Safari a un bug qui supprime la sémantique pour les éléments de type table et button dans la version 16), mais si vous vous trouvez d'une manière ou d'une autre dans cette situation, évitez-la à tout prix.

Propriété de commande de Grid et Flex

Grid et flexbox ont changé ce que nous pouvons faire avec la création de mises en page. Ce sont des outils incroyables qui nous aident à créer des mises en page aussi compliquées que nous le souhaitons, mais n'oubliez pas qu'ils peuvent créer des problèmes d'accessibilité.

Comme Manuel Matuzović l'a mentionné dans son exposé The Dark Side of the Grid, lorsque nous modifions l'ordre des éléments visuellement, soit en définissant un ordre explicite dans une grille avec des propriétés telles que grid-row et grid-column, soit en utilisant la propriété order sur flexbox ou grid, l'ordre d'apparition des éléments dans le DOM ne sera pas modifié.

Ce décalage entre l'ordre DOM et l'ordre visuel peut créer une expérience déroutante pour de nombreux utilisateurs, y compris les utilisateurs de clavier. Si nous modifions trop l'ordre visuel, cela peut créer une expérience déroutante pour eux, car la navigation au clavier pourrait ne pas fonctionner logiquement. Comme je l'ai mentionné dans la section sur le tabindex positif, le critère WCAG 2.4.3 - Ordre de focus, cette navigation au clavier doit préserver un ordre qui "préserve le sens et l'opérabilité."

Vérifions cela à l'aide d'un exemple. Jetons un coup d'œil à ce balisage, et ordonnons-les à l'aide d'une grille :

<ul role="list">
  <li><button>1</button></li>
  <li><button>2</button></li>
  <li><button>3</button></li>
  <li><button>4</button></li>
  <li><button>5</button></li>
  <li><button>6</button></li>
  <li><button>7</button></li>
  <li><button>8</button></li>
  <li><button>9</button></li>
</ul>
button:focus {
  outline: max(2px, 0.08em) solid currentColor;
  outline-offset: -7px;
}

@supports selector(:focus-visible) {
  button:focus {
    outline: none;
  }

  button:focus-visible {
    outline: max(2px, 0.08em) solid currentColor;
    outline-offset: -7px;
  }
}
9 boutons bleus sur 3 colonnes, dans l'ordre numérique 1, 2, 3, puis ligne suivante 4, 5, 6, puis ligne suivante 7, 8, 9.

Si vous utilisez la navigation au clavier, vous remarquerez que l'ordre est assez simple. Il se lit de gauche à droite et de haut en bas, et la navigation sera la même. Utilisons maintenant les propriétés de la grille pour effectuer quelques modifications :

ul
  li:where(:nth-child(1), :nth-child(5), :nth-child(7), :nth-child(9)) {
  grid-row: span 2;
  grid-column: span 2;
}

ul li:where(:nth-child(1), :nth-child(5)) {
  order: 2;
}

ul li:where(:nth-child(7), :nth-child(8)) {
  order: -1;
}

ul li:nth-child(4) {
  grid-row: 3;
  grid-column: 2 / span 2;
}

ul li:nth-child(3) {
  grid-row: 5 / span 3;
  grid-column: 3;
}
L'ordre de l'image prcédente n'est plus respecté, on 7, 8, 2, etc.

Maintenant, il a l'air complètement désorganisé. Bien sûr, la mise en page a l'air drôle, mais lorsque vous commencez à y naviguer avec la touche Tab, l'ordre est très aléatoire. Il y a un certain degré de prévisibilité maintenant parce que j'ai utilisé des chiffres comme étiquette du bouton, mais que se passe-t-il s'ils ont un contenu différent ? Il serait impossible de prédire quel sera le prochain bouton focalisé avec un clavier.

C'est le genre de scénario qu'il faut éviter. Cela ne signifie pas que vous ne pouvez pas ordonner explicitement un élément dans une grille ou utiliser la propriété order. Cela signifie que vous devez faire attention à la gestion de vos mises en page et vous assurer que l'ordre visuel et l'ordre du DOM correspondent autant que possible.

À propos, si vous voulez l'essayer par vous-même, vous pouvez voir la démo de ce code ici et expérimenter par vous-même cette navigation chaotique au clavier :

voir Focus order demo de smashingmag dans CodePen

Quelques modèles de composants

Avec ce que nous avons vu sur HTML et CSS, nous pouvons créer quelques composants simples pour améliorer l'expérience des utilisateurs de clavier.

Accordéons

Nous pouvons créer des accordéons accessibles au clavier avec juste du HTML grâce aux éléments details et summary. Il dispose d'une navigation au clavier par défaut, et la prise en charge des lecteurs d'écran est assez bonne. Attention toutefois à certaines interactions entre les lecteurs d'écran et les navigateurs, comme le souligne Scott O'Hara dans son article sur les éléments details et summary, certaines interactions ne montrent pas de changements importants lorsque les utilisateurs interagissent avec elles. Vous pourriez donc probablement l'améliorer avec JavaScript pour prendre en charge ces cas, mais l'accessibilité de ce composant est plutôt excellente par défaut, notamment pour la navigation au clavier, qui est notre principale préoccupation dans cet article !

Voici la structure HTML :

<details>
  <summary>
    <h2>Titre</h2>
    <span aria-hidden="true"></span>
  </summary>
  <p>
    <!-- Contenu -->
  </p>
</details>

Et voici à quoi cela ressemblerait lorsque les composants sont dans leur état contracté et développé :

3 questions sur 3 lignes distinctes, avec chacune un bouton qui semble indiquer qu'en cliquant dessus on aura une réponse.
Le bouton a été cliqué et on a bien une réponse à la question posée.

Commençons maintenant à styliser ce composant ! Par défaut, cet élément utilise ce triangle pour indiquer si l'élément détails est ouvert ou fermé. Nous pouvons supprimer cela en ajoutant cette règle à l'élément summary.

summary {
  list-style: none;
}

Mais nous aurons toujours besoin d'un indicateur visuel pour montrer s'il est ouvert ou fermé. Ma solution consiste à ajouter un deuxième élément en tant qu'enfant de summary. La partie importante est que cet élément aura l'attribut aria-hidden="true" :

<summary>
  <p>Combien coûte l'expédition ?</p>
  <span aria-hidden="true"></span>
</summary>

La raison pour laquelle j'ai caché cet élément span est que nous allons modifier son contenu à l'aide de CSS modifiant le pseudo-élément ::before, et que le contenu que nous ajoutons sera lu par un lecteur d'écran, à moins, bien sûr, que nous le cachions.

Cela dit, nous pouvons le modifier car le navigateur gère l'état ouvert de l'élément details en ajoutant l'attribut open au conteneur. Nous pouvons donc ajouter et modifier le contenu à l'aide de ces règles CSS :

summary span[aria-hidden='true']::before {
  content: '+';
}

details[open] summary span[aria-hidden='true']::before {
  content: '-';
}

Maintenant, vous pouvez ajouter le style dont vous avez besoin pour l'adapter (n'oubliez pas d'utiliser les états de focus adéquats !). Vous pouvez consulter cette démo que j'ai réalisée pour voir comment cela fonctionne. Testez-la avec un clavier, et vous remarquerez que vous pouvez interagir avec elle sans problème.

voir Details and summary demo de smashingmag dans CodePen

Comme je l'ai mentionné, cette approche ne nécessite aucun JavaScript, mais ce n'est pas le seul modèle que vous pouvez utiliser pour le balisage ! Si vous voulez en savoir plus sur le balisage des composants en accordéon, vous pouvez lire cet article de Sara Soueidan à ce sujet.

Sauter les liens

Parfois, lorsque vous naviguez sur un site, vous pouvez trouver de grands blocs d'éléments focalisables par le clavier, comme dans un menu, par exemple. Or bien souvent l'utilisateur veut juste interagir avec le contenu principal (main), donc offrir un moyen de sauter ces blocs d'éléments interactifs est important . Il existe même un critère WCAG pour ce cas.

Un mécanisme est disponible pour contourner les blocs de contenu qui sont répétés sur plusieurs pages Web.

Critère de réussite 2.4.1 : Contourner les blocs

C'est là que les "liens de saut" entrent en jeu ! Les liens de saut sont des liens qui ne sont généralement visibles que lorsqu'un utilisateur appuie sur la touche Tab, et qui vous permettent d'accéder aux points d'intérêt d'une page. Normalement, c'est pour vous amener au contenu principal, comme vous pouvez le remarquer sur YouTube, par exemple :

un lien de saut dans une page YouTube : 'skip navigation'

Mais il peut y avoir plusieurs liens de saut dans un site qui vous mèneront à diverses parties du site, comme le fait Smashing Magazine. Lorsque vous utilisez la touche de tabulation pour naviguer sur ce site, vous remarquerez qu'il y a trois liens de saut, qui vous amènent tous à des points importants de la page :

3 liens de saut, le premier vers le contenu principal, le deuxième vers la liste des articles, le troisième vers tous les sujets.

Ils sont généralement situés dans le header du site, mais ce n'est pas toujours le cas. Vous pouvez les ajouter là où c'est nécessaire, comme le montre Manuel Matuzović dans le tweet qui suit. Il a ajouté un lien de saut inline à un projet parce que la carte interactive comporte beaucoup d'éléments focalisables avec le clavier.

Je travaille sur une fonctionnalité qui permet aux utilisateurs de sauter les zones comportant de nombreux arrêts de tabulation (lien de saut en ligne). 🔥

Vidéo alt : Une page avec un tas de liens suivis d'une carte intégrée. L'appui sur la touche `Tab` révèle un lien qui, lorsqu'il est activé, déplace le focus vers l'élément tabulable suivant, après la carte.

Manuel Matuzović (@mmatuzo) 6 avril 2022

Maintenant, puisque l'utilité des liens de saut est claire, créons-en un. C'est très simple, il nous suffit de créer un élément a qui vous amène à l'élément souhaité :

<header>
  <a class="skip-link" href="#main-content">Go to main content</a>
</header>
<main id="main-content"></main>

Ensuite, nous devons masquer visuellement l'élément a. Ce que je fais ici, c'est utiliser la propriété CSS transform pour le retirer de la portée visuelle :

.skip-link {
  display: block;
  transform: translate(-9999px);
}

Ensuite, nous le déplaçons à la position nécessaire lorsque l'élément est focalisé :

.skip-link:focus {
  transform: translate(0);
}

Et c'est tout ! La création d'un lien de saut est facile et bien utile pour l'accessibilité au clavier.

Tooltips

Ces petites bulles de texte qui affichent des informations supplémentaires sur un élément peuvent également être réalisées avec du CSS pur, mais un petit avertissement ici : il est suggéré que vous pouvez fermer une infobulle en appuyant sur la touche Echap, ce qui n'est possible qu'avec JavaScript. J'expliquerai comment ajouter cette fonctionnalité dans la deuxième partie de cet article, mais tout le reste peut être fait de manière très simple en utilisant uniquement HTML et CSS.

Un problème courant avec les infobulles est qu'un utilisateur du clavier ne peut pas les voir, nous devons donc nous assurer que le composant qui les déclenche est un élément focalisable par le clavier. Notre meilleure chance est d'utiliser l'élément bouton. La sémantique est vraiment simple, comme le montre Heydon Pickering dans son livre Inclusive Components.

<div class="tooltip-container">
  <button></button>
  <div role="tooltip"></div>
</div>

Le conteneur avec la classe tooltip-container est là juste pour nous permettre de manipuler la position du conteneur avec l'attribut role="tooltip" plus tard en utilisant CSS. A propos de cet élément, on pourrait penser que ce rôle ajoute suffisamment de sémantique pour le faire fonctionner, mais en fait, ce n'est pas le cas, nous devrons donc compter sur deux d'attributs aria pour le lier à notre bouton.

Cet attribut dépend de l'intention de l'infobulle. Si vous envisagez de l'utiliser pour nommer un élément, vous devez utiliser l'attribut aria-labelledby :

<div class="tooltip-container">
  <button aria-labelledby="tooltip1">
    <svg aria-hidden="true">
      <!-- Contenu du SVG -->
    </svg>
  </button>
  <div id="tooltip1" role="tooltip">Parc d'achat</div>
</div>

Par contre, si vous souhaitez utiliser l'infobulle pour décrire ce que fait un élément, vous devrez le lier à l'aide de l'attribut aria-describedby :

<div class="tooltip-container">
  <button aria-label="Panier d'achat" aria-describedby="tooltip2">
    <svg aria-hidden="true">
      <!-- Contenu du SVG -->
    </svg>
  </button>
  <div id="tooltip2" role="tooltip">
    Vérifier, modifier et terminer votre achat
  </div>
</div>

Soyez prudent avec cette approche ; utilisez-la uniquement pour donner des descriptions auxiliaires, et non pour donner des informations absolument nécessaires pour comprendre ce que fait cet élément. En effet, lorsqu'un utilisateur de lecteur d'écran génère une liste des éléments de formulaire (y compris les boutons) du site, la description ne s'affichera que si l'utilisateur se concentre sur l'élément, comme le montre Adrian Roselli dans son test sur l'attribut aria-description.

Maintenant, il est temps de parler de ce qui nous préoccupe dans cet article : l'accessibilité au clavier ! Pour cela, nous devons masquer l'infobulle et l'afficher jusqu'à ce que l'utilisateur place le pointeur sur l'élément ou qu'il le fasse avec un clavier. Pour cela, nous utiliserons les pseudo-classes :hover et :focus en tandem avec le combinateur adjacent sibling.

Par ailleurs, il est important que vous puissiez voir l'infobulle lorsque vous la survolez afin de respecter le critère WCAG 1.4.13 : Content on Hover or Focus. Avec ces considérations à l'esprit, voici à quoi devrait ressembler notre code :

[role='tooltip'] {
  position: absolute;
  bottom: 0;
  gauche: 50%;
  display: none;
  transform: translate(-50%, 100%);
}

button:hover + [role='tooltip'],
button:focus + [role='tooltip'],
[role='tooltip']:hover {
  display: block;
}

Et voilà comment créer une infobulle accessible au clavier à l'aide de HTML et CSS. Vous pouvez vérifier le comportement des deux exemples d'infobulles dans cette démo. N'oubliez pas que ce n'est pas entièrement prêt pour la production. Vous avez besoin de JavaScript pour fermer l'infobulle lorsque vous appuyez sur la touche Echap. Nous aborderons ce point plus tard dans la prochaine partie de cet article, alors gardez-le à l'esprit.

voir Tooltip demo - CSS only de smashingmag dans CodePen

Comme le mentionne Heydon dans son livre, les infobulles ont un problème lorsque vous les utilisez pour des appareils qui n'ont pas de pointeur, comme les téléphones portables ou les tablettes, il faut alors adopter une approche différente pour elles. Vous pouvez utiliser CSS pour cela en utilisant les media queries hover et pointer, comme je l'explique dans mon article.

Récapitulatif

L'accessibilité du clavier est une partie essentielle de l'accessibilité. J'espère que cet article vous a aidé à comprendre à quel point HTML et CSS sont cruciaux pour faire de la navigation au clavier une expérience utilisateur agréable et accessible. Mais ce n'est pas la fin de l'accessibilité du clavier ! Je vais aborder la façon dont nous pouvons utiliser JavaScript pour manipuler la navigation au clavier et comment nous pouvons l'utiliser dans des modèles de composants plus complexes.

Lire la deuxième partie dans La Cascade

Autres ressources externes

Articles de Cristian Diaz traduits dans La Cascade

Voir la page de Cristian Diaz et la liste de ses articles dans La Cascade.
Article original paru le 14 novembre 2022 dans Smashing Magazine
Traduit avec l'aimable autorisation de Smashing Magazine et de Cristian Diaz.
Copyright Smashing Magazine © 2022