Quand CSS ne suffit pas : exigences JavaScript pour les composants accessibles
Publié: 2022-03-10En tant qu'auteur de ModernCSS.dev, je suis un grand partisan des solutions CSS. Et j'adore voir les façons intelligentes dont les gens utilisent CSS pour des conceptions et une interactivité vraiment prêtes à l'emploi ! Cependant, j'ai remarqué une tendance à promouvoir des composants "CSS uniquement" en utilisant des méthodes telles que le "hack de cases à cocher". Malheureusement, des hacks comme ceux-ci laissent un nombre important d'utilisateurs incapables d'utiliser votre interface.
Cet article couvre plusieurs composants courants et pourquoi CSS n'est pas suffisant pour couvrir l'accessibilité en détaillant les exigences JavaScript. Ces exigences sont basées sur les directives pour l'accessibilité des contenus Web (WCAG) et sur des recherches supplémentaires menées par des experts en accessibilité. Je ne prescrirai pas de solutions JavaScript ou de démo CSS, mais examinerai plutôt ce qui doit être pris en compte lors de la création de chaque composant. Un framework JavaScript peut certainement être utilisé mais n'est pas nécessaire pour ajouter les événements et fonctionnalités évoqués.
Les exigences répertoriées ne sont généralement pas facultatives - elles sont nécessaires pour garantir l'accessibilité de vos composants.
Si vous utilisez une infrastructure ou une bibliothèque de composants, vous pouvez utiliser cet article pour vous aider à évaluer si les composants fournis répondent aux exigences d'accessibilité . Il est important de savoir que de nombreux éléments notés ne seront pas entièrement couverts par des outils de test d'accessibilité automatisés comme aXe, et nécessitent donc des tests manuels. Ou, vous pouvez utiliser un framework de test comme Cypress pour créer des tests pour la fonctionnalité requise.
Gardez à l'esprit que cet article vise à vous informer des considérations JavaScript pour chaque composant d'interface. Ce n'est pas une ressource complète pour tous les détails de mise en œuvre pour la création de composants entièrement accessibles, tels que l'aria nécessaire ou même le balisage. Des ressources sont incluses pour chaque type afin de vous aider à en savoir plus sur les considérations plus larges pour chaque composant.
Déterminer si CSS uniquement est une solution appropriée
Voici quelques questions à poser avant de poursuivre avec une solution CSS uniquement. Nous aborderons certains des termes présentés ici plus en contexte avec leurs composants associés.
- Est-ce pour votre propre plaisir ?
Alors allez-y absolument sur CSS, repoussez les limites et apprenez ce que le langage peut faire ! - La fonctionnalité inclut-elle l'affichage et le masquage du contenu ?
Ensuite, vous avez besoin de JS pour basculer au minimum aria et pour activer la fermeture surEsc
. Pour certains types de composants qui changent également d'état, vous devrez peut-être également communiquer les modifications en déclenchant des mises à jour dans une région active ARIA. - L'ordre de mise au point naturelle est-il le plus idéal ?
Si l'ordre naturel perd la relation entre un déclencheur et l'élément qu'il a déclenché, ou si un utilisateur du clavier ne peut même pas accéder au contenu via l'ordre de tabulation naturel, alors vous avez besoin de JS pour aider à la gestion du focus. - Le contrôle stylisé offre-t-il les informations correctes sur la fonctionnalité ?
Les utilisateurs de technologies d'assistance telles que les lecteurs d'écran reçoivent des informations basées sur la sémantique et ARIA qui les aident à déterminer ce que fait un contrôle. De plus, les utilisateurs de la reconnaissance vocale doivent être en mesure d'identifier l'étiquette ou le type du composant pour déterminer la phrase à utiliser pour faire fonctionner les commandes. Par exemple, si votre composant est conçu comme des onglets mais utilise des boutons radio pour "fonctionner" comme des onglets, un lecteur d'écran peut entendre "bouton radio" et un utilisateur vocal peut essayer d'utiliser le mot "onglet" pour les faire fonctionner. Dans ces cas, vous aurez besoin de JS pour activer l'utilisation des contrôles et de la sémantique appropriés pour obtenir la fonctionnalité souhaitée. - L'effet repose-t-il sur le survol et/ou la mise au point ?
Ensuite, vous aurez peut-être besoin de JS pour vous aider dans une solution alternative pour fournir un accès égal ou persistant au contenu, en particulier pour les utilisateurs d'écran tactile et ceux qui utilisent un zoom de bureau de 200 % ou un logiciel de grossissement.
Petite astuce : Une autre référence lorsque vous créez n'importe quel type de contrôle personnalisé est la liste de contrôle du développement accessible du contrôle personnalisé du guide W3 « Utilisation d'ARIA ». Cela mentionne plusieurs points ci-dessus, avec quelques considérations de conception et de sémantique supplémentaires.
Info-bulles
Affiner la définition d'une info-bulle est un peu délicat, mais pour cette section, nous parlons de petites étiquettes de texte qui apparaissent au survol de la souris près d'un élément déclencheur. Ils se superposent à d'autres contenus, ne nécessitent aucune interaction et disparaissent lorsqu'un utilisateur supprime le survol ou le focus.
La solution CSS uniquement ici peut sembler tout à fait correcte et peut être réalisée avec quelque chose comme :
<button class="tooltip-trigger">I have a tooltip</button> <span class="tooltip">Tooltip</span> .tooltip { display: none; } .tooltip-trigger:hover + .tooltip, .tooltip-trigger:focus + .tooltip { display: block; }
Cependant, cela ignore toute une liste de problèmes d'accessibilité et empêche de nombreux utilisateurs d'accéder au contenu de l'info-bulle.
Un grand groupe d'utilisateurs exclus sont ceux qui utilisent des écrans tactiles où :hover
ne sera peut-être pas déclenché puisque sur les écrans tactiles, un événement :hover
se déclenche en synchronisation avec un événement :focus
. Cela signifie que toute action associée liée à l'élément déclencheur - comme un bouton ou un lien - se déclenchera parallèlement à l'info-bulle révélée. Cela signifie que l'utilisateur peut manquer l'info-bulle ou ne pas avoir le temps de lire son contenu.
Dans le cas où l'info-bulle est attachée à un élément interactif sans événements, l'info-bulle peut s'afficher mais ne pas être masquée jusqu'à ce qu'un autre élément obtienne le focus, et dans l'intervalle peut bloquer le contenu et empêcher un utilisateur d'effectuer une tâche.
De plus, les utilisateurs qui ont besoin d'utiliser un logiciel de zoom ou d'agrandissement pour naviguer rencontrent également un obstacle important à l'utilisation des info-bulles. Étant donné que les info-bulles sont révélées au survol, si ces utilisateurs doivent modifier leur champ de vision en faisant un panoramique de l'écran pour lire l'info-bulle, cela peut la faire disparaître. Les info-bulles enlèvent également le contrôle à l'utilisateur car il n'y a souvent rien à dire à l'utilisateur qu'une info-bulle apparaîtra à l'avance. La superposition de contenu peut les empêcher d'accomplir une tâche. Dans certaines circonstances, comme une info-bulle liée à un champ de formulaire, les claviers mobiles ou autres à l'écran peuvent masquer le contenu de l'info-bulle. Et, s'ils ne sont pas correctement connectés à l'élément déclencheur, certains utilisateurs de technologies d'assistance peuvent même ne pas savoir qu'une info-bulle est apparue.
Les conseils pour le comportement des info-bulles proviennent du critère de succès 1.4.13 des WCAG — Contenu au survol ou au focus. Ce critère est destiné à aider les utilisateurs malvoyants et ceux qui utilisent des logiciels de zoom et de grossissement. Les principes directeurs de l'info-bulle (et d'autres contenus apparaissant au survol et au focus) incluent :
- Rejetable
L'info-bulle peut être ignorée sans déplacer le survol ou le focus - Hoverable
Le contenu de l'info-bulle révélé peut être survolé sans qu'il ne disparaisse - Persistant
Le contenu supplémentaire ne disparaît pas en fonction d'un délai d'attente, mais attend qu'un utilisateur supprime le survol ou le focus ou le rejette d'une autre manière
Pour respecter pleinement ces directives, une assistance JavaScript est nécessaire, en particulier pour permettre de supprimer le contenu.
- Les utilisateurs de technologie d'assistance supposeront que le comportement de rejet est lié à la touche Échap , qui nécessite un écouteur JavaScript.
- Selon les recherches de Sarah Higley décrites dans la section suivante, l'ajout d'un bouton "fermer" visible dans l'info-bulle nécessiterait également que JavaScript gère son événement de fermeture.
- Il est possible que JavaScript ait besoin d'augmenter votre solution de style pour s'assurer qu'un utilisateur peut survoler le contenu de l'info-bulle sans le faire disparaître pendant que l'utilisateur déplace sa souris.
Alternatives aux info-bulles
Les info-bulles doivent être un dernier recours. Sarah Higley — une experte en accessibilité qui a une passion particulière pour dissuader l'utilisation des info-bulles — propose ce test simple :
"Pourquoi est-ce que j'ajoute ce texte à l'interface utilisateur ? Où d'autre pourrait-il aller?
— Sarah Higley de la présentation « Tooltips : Investigation Into Four Parts »
Sur la base des recherches auxquelles Sarah a participé pour son rôle chez Microsoft, une solution alternative est un "toggletip" dédié. Cela signifie essentiellement fournir un élément supplémentaire pour permettre à un utilisateur de déclencher intentionnellement l' affichage et le masquage de contenu supplémentaire . Contrairement aux info-bulles, les bascules peuvent conserver la sémantique des éléments dans le contenu révélé. Ils redonnent également à l'utilisateur le contrôle de leur basculement, et conservent la découvrabilité et l'opérabilité par plus d'utilisateurs et en particulier les utilisateurs d'écran tactile.
Si vous vous souvenez que l'attribut title
existe, sachez simplement qu'il souffre des mêmes problèmes que ceux que nous avons notés dans notre solution CSS uniquement. En d'autres termes, n'utilisez pas le title
en supposant qu'il s'agit d'une solution d'info-bulle acceptable.
Pour plus d'informations, consultez la présentation de Sarah sur YouTube ainsi que son article détaillé sur les info-bulles. Pour en savoir plus sur les info-bulles par rapport aux bascules et un peu plus d'informations sur pourquoi ne pas utiliser title
, consultez l'article de Heydon Pickering dans Inclusive Components: Tooltips and Toggletips.
Modaux
Les modaux - alias lightboxes ou boîtes de dialogue - sont des fenêtres sur la page qui apparaissent après une action de déclenchement. Ils recouvrent le contenu d'autres pages, peuvent contenir des informations structurées, y compris des actions supplémentaires, et ont souvent un arrière-plan semi-transparent pour aider à distinguer la fenêtre modale du reste de la page.
J'ai vu quelques variantes d'un modal CSS uniquement (et je suis coupable d'en avoir créé un pour une ancienne version de mon portfolio). Ils peuvent utiliser le "hack de case à cocher", utiliser le comportement de :target
, ou essayer de le façonner à partir de :focus
(qui est probablement vraiment une info-bulle trop grande déguisée).
Quant à l'élément de dialog
HTML, sachez qu'il n'est pas considéré comme entièrement accessible. Ainsi, bien que j'encourage absolument les gens à utiliser le HTML natif avant les solutions personnalisées, malheureusement, celui-ci brise cette idée. Vous pouvez en savoir plus sur les raisons pour lesquelles la boîte de dialog
HTML n'est pas accessible.
Contrairement aux info-bulles, les modaux sont destinés à permettre un contenu structuré. Cela signifie potentiellement un titre, du contenu de paragraphe et des éléments interactifs comme des liens, des boutons ou même des formulaires. Pour que la plupart des utilisateurs puissent accéder à ce contenu, ils doivent pouvoir utiliser les événements du clavier , en particulier la tabulation. Pour un contenu modal plus long, les touches fléchées doivent également conserver la possibilité de faire défiler. Et comme les info-bulles, elles doivent pouvoir être ignorées avec la touche Échap - et il n'y a aucun moyen de l'activer avec CSS uniquement.
JavaScript est requis pour la gestion du focus dans les modaux. Les modaux doivent piéger le focus, ce qui signifie qu'une fois que le focus est dans le modal, un utilisateur ne doit pas pouvoir en sortir dans le contenu de la page derrière lui. Mais d'abord, l'accent doit être mis sur le modal, ce qui nécessite également JavaScript pour une solution modale entièrement accessible.
Voici la séquence d'événements liés aux modaux qui doivent être gérés avec JavaScript :
- L'écouteur d'événement sur un bouton ouvre le modal
- Le focus est placé dans le modal ; quel élément varie en fonction du contenu modal (voir arbre de décision)
- Le focus est piégé dans le modal jusqu'à ce qu'il soit rejeté
- De préférence, un utilisateur peut fermer un modal avec la touche Esc en plus d'un bouton de fermeture dédié ou d'une action de bouton destructrice telle que "Annuler" si la reconnaissance du contenu modal est requise
- Si Esc est autorisé, les clics sur le fond modal doivent également rejeter le modal
- Lors du rejet, si aucune navigation n'a eu lieu, le focus est replacé sur l'élément de bouton de déclenchement
Arbre de décision de focalisation modale
Sur la base de l'exemple de dialogue modal WAI-ARIA Authoring Practices, voici un arbre de décision simplifié indiquant où placer le focus une fois qu'un modal est ouvert. Le contexte dictera toujours le choix ici, et idéalement la mise au point est gérée plus loin que simplement "le premier élément focalisable". En fait, il faut parfois sélectionner des éléments non focalisables.
- Le sujet principal du modal est une forme.
Focus sur le premier champ de formulaire. - Le contenu modal est important en longueur et repousse les actions modales hors de vue.
Concentrez-vous sur un titre s'il est présent ou sur le premier paragraphe. - Le but du modal est procédural (exemple : confirmation de l'action) avec plusieurs actions disponibles.
Concentrez-vous sur l'action « la moins destructrice » en fonction du contexte (exemple : « OK »). - Le but du modal est procédural avec une action.
Concentrez-vous sur le premier élément focalisable
Petite astuce : dans le cas où vous devez focaliser un élément non focalisable, tel qu'un titre ou un paragraphe, ajoutez tabindex="-1"
qui permet à l'élément de devenir focalisable par programme avec JS mais ne l'ajoute pas à l'ordre de tabulation DOM .
Reportez-vous à la démo modale WAI-ARIA pour plus d'informations sur les autres exigences de configuration d'ARIA et des détails supplémentaires sur la façon de sélectionner l'élément auquel ajouter le focus. La démo inclut également JavaScript pour illustrer comment gérer la mise au point.
Pour une solution prête à l'emploi, Kitty Giraudel a créé a11y-dialog qui inclut les exigences de fonctionnalités dont nous avons discuté. Adrian Roselli a également fait des recherches sur la gestion de la focalisation des dialogues modaux et a créé une démo et compilé des informations sur la façon dont différentes combinaisons de navigateur et de lecteur d'écran communiqueront l'élément ciblé.
Onglets
Les interfaces à onglets impliquent une série de déclencheurs qui affichent les panneaux de contenu correspondants un par un. Les "hacks" CSS que vous pouvez trouver pour ceux-ci impliquent l'utilisation de boutons radio stylisés, ou :target
, qui permettent tous deux de ne révéler qu'un seul panneau à la fois.
Voici les fonctionnalités d'onglet qui nécessitent JavaScript :
- Basculer l'attribut
aria-selected
sur true pour l'onglet actuel et false pour les onglets non sélectionnés - Création d'un tabindex itinérant pour distinguer la sélection d'onglets du focus
- Déplacer le focus entre les onglets en répondant aux événements des touches fléchées (et éventuellement
Home
etEnd
)
En option, vous pouvez faire en sorte que la sélection des onglets suive le focus, ce qui signifie que lorsqu'un onglet est ciblé, il est également sélectionné et affiche son panneau d'onglets associé. Les pratiques de création WAI-ARIA proposent ce guide pour choisir si la sélection doit suivre l'orientation.
Que vous choisissiez ou non que la sélection suive le focus, vous utiliserez également JavaScript pour écouter les événements des touches fléchées afin de déplacer le focus entre les éléments de l'onglet. Il s'agit d'un modèle alternatif pour permettre la navigation dans les options de tabulation puisque l'utilisation d'un tabindex itinérant (décrit ci-après) modifie l'ordre naturel de mise au point des tabulations du clavier.
À propos tabindex
Le concept d'un tabindex itinérant est que la valeur de la valeur tabindex
est contrôlée par programme pour gérer l'ordre de focus des éléments. En ce qui concerne les onglets, cela signifie que seul l'onglet sélectionné fait partie de l'ordre de focus en définissant tabindex="0"
, et les onglets non sélectionnés sont définis sur tabindex="-1"
qui les supprime de l'ordre de focus naturel du clavier.
La raison en est que lorsqu'un onglet est sélectionné, l'onglet suivant attirera l'attention de l'utilisateur dans le panneau d'onglets associé. Vous pouvez choisir de rendre l'élément qui est le panneau d'onglets focusable en lui attribuant tabindex="0"
, ou cela peut ne pas être nécessaire s'il existe une garantie d'un élément focusable dans le panneau d'onglets . Si le contenu de votre panneau d'onglets sera plus variable ou complexe, vous pouvez envisager de gérer le focus en fonction de l'arbre de décision que nous avons examiné pour les modaux.
Exemples de modèles d'onglets
Voici quelques modèles de référence pour créer des onglets :
- Démo Tabpanel de l'Université Deque
- Tests de widget d'onglet de Scott O'Hara (teste plusieurs modèles fonctionnels)
- Interfaces à onglets de Heydon Pickering's Inclusive Components , qui montre comment les onglets peuvent être une amélioration progressive d'une table des matières
Carrousels
Aussi appelés diaporamas ou curseurs, les carrousels impliquent une série de panneaux de contenu rotatifs (alias « diapositives ») qui incluent des mécanismes de contrôle. Vous les trouverez dans de nombreuses configurations avec un large éventail de contenus. Ils sont notoirement considérés comme un mauvais modèle de conception.
La partie délicate des carrousels CSS uniquement est qu'ils peuvent ne pas offrir de contrôles, ou ils peuvent utiliser des contrôles inattendus pour manipuler le mouvement du carrousel. Par exemple, vous pouvez à nouveau utiliser le "hack de case à cocher" pour provoquer la transition du carrousel, mais les cases à cocher transmettent le mauvais type d'informations sur l'interaction aux utilisateurs de la technologie d'assistance. De plus, si vous stylisez les étiquettes des cases à cocher pour qu'elles apparaissent visuellement sous forme de flèches vers l'avant et vers l'arrière, vous risquez de donner aux utilisateurs de logiciels de reconnaissance vocale une mauvaise impression de ce qu'ils doivent dire pour contrôler le carrousel.
Plus récemment, le support CSS natif pour l'accrochage au défilement a atterri. Au début, cela semble être la solution parfaite pour CSS uniquement. Mais, même la vérification automatisée de l'accessibilité les signalera comme non navigables par les utilisateurs de clavier au cas où il n'y aurait aucun moyen de les parcourir via des éléments interactifs. Il existe d'autres problèmes d'accessibilité et d'expérience utilisateur avec le comportement par défaut de cette fonctionnalité, dont certains que j'ai inclus dans ma démo de capture de défilement sur SmolCSS.
Malgré le large éventail d'apparences des carrousels, il existe certains traits communs. Une option consiste à créer un carrousel à l'aide d'un balisage d'onglets, car il s'agit en fait de la même interface sous-jacente avec une présentation visuelle modifiée. Par rapport aux onglets, les carrousels peuvent offrir des commandes supplémentaires pour le précédent et le suivant, ainsi qu'une pause si le carrousel est en lecture automatique.
Voici les considérations JavaScript en fonction des fonctionnalités de votre carrousel :
- Utilisation des contrôles paginés
Lors de la sélection d'un élément numéroté, concentrez par programmation la diapositive de carrousel associée. Cela impliquera la configuration de conteneurs de diapositives à l'aide d'un tabindex itinérant afin que vous puissiez vous concentrer sur la diapositive actuelle, mais empêcher l'accès aux diapositives hors écran. - Utilisation de la lecture automatique
Incluez un contrôle de pause et activez également la pause lorsque la diapositive est survolée ou qu'un élément interactif à l'intérieur de celle-ci est mis au point. De plus, vous pouvez vérifier lesprefers-reduced-motion
dans JavaScript pour charger le diaporama dans un état de pause afin de respecter les préférences de l'utilisateur. - Utilisation des commandes Précédent/Suivant
Incluez un élément visuellement caché marqué commearia-live="polite"
et une fois ces contrôles activés, remplissez la région en direct avec une indication de la position actuelle, telle que "Diapositive 2 sur 4".
Ressources pour la construction de carrousels accessibles
- Détails et considérations d'implémentation approfondis ainsi qu'un exemple de code complet du didacticiel W3C Web Accessibility sur les carrousels
- Exemple de Deque University d'amélioration d'une interface d'onglets dans un carrousel
- L'exemple WAI-ARIA Authoring Practices d'un carrousel d'images à rotation automatique
- Une sélection de ressources de carrousel dans le tour d'horizon des composants accessibles de Smashing
Menus déroulants
Il s'agit d'un composant dans lequel un bouton permet d'ouvrir une liste de liens, généralement utilisée pour les menus de navigation. Les implémentations CSS qui s'arrêtent à afficher le menu sur :hover
ou :focus
ne manquent que quelques détails importants.
J'avoue que j'ai même pensé qu'en utilisant la nouvelle propriété :focus-within
, nous pourrions implémenter en toute sécurité une solution CSS uniquement. Vous verrez que mon article sur les menus déroulants CSS a été modifié pour inclure des notes et des ressources sur le JavaScript nécessaire (j'ai conservé le titre afin que d'autres personnes à la recherche de cette solution complètent également, espérons-le, l'implémentation de JS). Plus précisément, s'appuyer uniquement sur CSS signifie enfreindre le critère de succès 1.4.13 des WCAG : contenu survolé ou ciblé, dont nous avons pris connaissance avec les info-bulles.
Nous devons ajouter JavaScript pour certaines techniques qui devraient sembler familières à ce stade :
- Basculer
aria-expanded
sur le bouton de menu entretrue
etfalse
en écoutant les événements declick
- Fermeture d'un menu ouvert lors de l'utilisation de la touche Échap et retour du focus sur le bouton de basculement de menu
- De préférence, fermer les menus ouverts lorsque le focus est déplacé en dehors du menu
- Facultatif : implémentez les touches fléchées ainsi que les touches
Home
etEnd
pour la navigation au clavier entre les boutons de basculement de menu et les liens dans les listes déroulantes
Petite astuce : Assurez-vous de la bonne implémentation du menu déroulant en associant l'affichage du menu au sélecteur de .dropdown-toggle[aria-expanded=
"
true
"
] + .dropdown
plutôt que de baser l'affichage du menu sur la présence d'un JS- supplémentaire classe ajoutée comme active
. Cela supprime également une certaine complexité de votre solution JS !
Ceci est également appelé « modèle de divulgation » et vous pouvez trouver plus de détails dans le menu de navigation Exemple de divulgation des pratiques d'auteur WAI-ARIA.
Ressources supplémentaires sur la création de composants accessibles
- Guide complet de Smashing sur les composants frontaux accessibles
- Article de Carie Fisher Good, Better, Best : démêler le monde complexe des modèles accessibles
- Démos et informations sur les modèles de conception courants et les widgets disponibles dans WAI-ARIA Authoring Practices 1.2
- Bibliothèque de codes de l'Université Deque
- Composants accessibles de Scott O'Hara
- Composants inclusifs de Heydon Pickering