Note : cet article est la traduction de ma contribution au calendrier de l’avent de HTMHell, Modern HTML as a foundation for progressive enhancement !
Vous êtes peut-être familier avec le concept d’amélioration progressive. En résumé, c’est une méthode permettant de s’assurer que l’utilisateur dispose d’une version viable de votre page quelque soit son contexte — connexion limitée, navigateur désuet, etc. — mais aussi de rendre ladite page plus résiliente (par exemple aux erreurs JavaScript).
L’amélioration progressive débute par la base :
- le contenu,
- balisé avec HTML,
- stylé avec CSS,
- enrichi avec JavaScript,
- et amélioré pour l’accessibilité avec ARIA (en cas de besoin uniquement).
Chacune de ces étapes devrait fonctionner telle quelle et améliorer les étapes précédentes sans les abîmer. En d’autres termes, il vous faut rédiger votre HTML indépendamment du CSS ou du JavaScript que vous y appliquerez ensuite.
Cela étant dit, il paraît évident que mieux vous connaissez chaque étape de la liste, plus votre page devrait être robuste. JavaScript est omniprésent donc je présume que vous en êtes familier. ARIA devient de plus en plus visible depuis quelques années, donc on peut supposer que même sans connaître ARIA vous utilisez une bibliothèque ou un outil s’en occupant très bien. CSS s’améliore constamment et j’imagine que votre veille vous permet de découvrir des nouveautés quotidiennement ou presque…
Mais quid de HTML ? Fait-il partie de votre veille technique ? Voyez-vous fréquemment passer des nouveautés HTML dans vos flux d’information ? Pas très souvent, je présume.
Mais voilà. HTML est un standard vivant donc les spécifications changent, les navigateurs améliorent leurs supports en permanence — avec Interop 2022 par exemple — donc il y a des nouveautés, côté spécifications ou côté navigateurs ; et certains d’entre eux sont destinés à devenir des versions natives de composants JavaScript basés sur un amas de div
depuis des lustres.
Et si nous pouvions améliorer la couche HTML pour ce genre de composants, rendant le balisage plus résilient au passage ?
Avertissement : il faut voir HTML comme une fondation, en aucun cas un remplacement de votre composant JavaScript existant. Si votre composant requière ARIA, ne tentez pas de l’implémenter sans. Autrement dit, tentez systématiquement de fournir la meilleure expérience utilisateur possible et ne vous préoccupez pas trop de l’expérience développeur. Vous pourriez être intéressé par la série d’articles sur les composants sous-conçus d’Adrian Roselli.
Allons faire une ballade !
details
et summary
comme base pour le motif de conception disclosure
Remémorez-vous ces boutons « Voir plus » qui font apparaître des contenus supplémentaires quand vous les activez. Rendre ce genre de composant accessible nécessite généralement que vous implémentiez le motif de conception ARIA disclosure, basé sur un bouton et l’attribut aria-expanded
pour communiquer l’état.
<details>
et summary>
sont les candidats parfaits pour ça. Comme leur nom l’indique, ce motif de balisage va afficher un résumé (summary) et masquer les détails associés, mais les rendre disponibles lors de l’activation du résumé. L’implémentation par les navigateurs et le support sont excellents.
Ça semble plutôt sympa, non ? Alors pourquoi s’embarrasser avec le motif de conception disclosure et ne pas préférer utiliser <details>
et <summary>
systématiquement ? Pour faire simple, les interactions ne sont pas exactement celles attendues par vos utilisateurs, et le support par les navigateurs et technologies d’assistance n’est pas encore idéal — comme l’a démontré Scott O’Hara.
Mais alors… peut-on l’utiliser comme la fondation de notre motif de conception ARIA disclosure ? Découvrons ça (sur CodePen) !
Rien de magique ici : pour améliorer et harmoniser le support des technologies d’assistance, on transforme le motif HTML en disclosure en ajoutant à l’élément <summary>
le rôle button
et l’attribut aria-expanded
pour expliciter l’état, et en s’assurant que le contenu masqué l’est pour tout le monde avec l’attribut hidden
. L’attribut open
sur l’élément <details>
se charge de tout ça nativement, mais on ne peut pas se reposer dessus dès qu’on personnalise le marqueur triangle par défaut (ce qu’on fera à n’en pas douter) : on doit implémenter le motif de conception disclosure complet pour éviter des restitutions incohérentes entre navigateurs et technologies d’assistance.
De plus, saviez-vous que les navigateurs basés sur Chromium permettent de trouver le contenu masqué par <details>
lors d’une recherche sur la page ? C’est une fonctionnalité qui va être standardisée en HTML avec la valeur until-found
pour l’attribut hidden
mais ça n’est pas censé être le cas des contenus masqués par le motif de conception disclosure.
Comme vous l’avez peut-être compris, utiliser <details>
et <summary>
enrichis avec le motif de conception ARIA disclosure ne fera aucune différence pour la plupart des utilisateurs… mais si d’aventure votre JS ou votre CSS ne fonctionne pas, votre balisage sémantique prendra le relai et restera interactif — avec toutes ses limitations actuelles dans les technologies d’assistance.
Faites d’ailleurs attention en utilisant ces éléments comme fondation : ils ne sont pas le bon choix pour des accordéons, un menu déroulant, un menu « burger », un groupe d’onglets ou une fenêtre modale… Restez sémantiques !
Et si je vous disais qu’il y a d’autres éléments HTML améliorables progressivement de la sorte ? On jette un œil ?
output
comme une live region
Avez-vous déjà eu besoin d’alimenter une live region pour communiquer des changements aux utilisateurs de lecteurs d’écran — parfois masquée visuellement en CSS ? C’est assez fréquent de nos jours, et vous retrouverez une gestion des live regions dans la plupart des frameworks : Angular a un LiveAnnouncer
dans son CDK Accessibilité, et WordPress a un script interne wp.a11y.speak()
… Les live regions ARIA s’appuient sur trois rôles spécifiques : status
, log
et alert
, chacune ayant un comportement légèrement différent.
Mais saviez-vous qu’un élément HTML est une live region native, avec un rôle implicite status
? Je vous présente <output>
! L’implémentation par les navigateurs est complète et le support est excellent. Cependant certains couples de navigateurs et technologies d’assistance précis sont défectueux, comme Scott O’Hara (à nouveau) l’a démontré.
Rendons <output>
encore plus robuste en le transformant en live region ARIA (sur CodePen) !
Vous vous en souvenez peut-être, expliciter les rôles des éléments HTML était nécessaire il y a quelques années — pour les landmarks, principalement — afin d’améliorer le support des navigateurs et technologies d’assistance. C’est d’ailleurs toujours une pratique encouragée par le critère 12.6 du RGAA. Nous nous sommes habitués à écrire <main role="main">
, <header role="banner">
, etc.
Un autre point positif avec <output role="status">
est que ça vous permet de styler vos live regions en sélectionnant l’élément output
: spécificité moins élevée, et la possibilité d’appliquer des styles de base renforcés — avec CSS containment, par exemple ?
Une live region particulière : le toast !
Il existe aussi un cas d’usage pour une live region affichée visuellement. Je n’irais pas très loin sur le sujet, car il a déjà été traité dans un grand nombre d’articles de grande qualité :
- Scott O’Hara l’a mentionné dans The Output Element,
- une précision technique après A toast to an accessible toast… abordant les considérations d’expérience utilisateur,
- mais aussi Adrian Roselli avec Defining toast message.
Attention : si votre toast ou votre live region contient des éléments interactifs, vous devriez probablement utiliser un rôle dialog
ou alertdialog
au lieu d’un élément <output>
. Cela dit… il y a peut-être un élément HTML plus indiqué pour ça !
Une boîte de dialog
Je ne vais pas creuser beaucoup l’élément <dialog>
, mais explorons tout de même ce qu’il fait nativement comparé au modèle de conception ARIA dialog :
- il a un rôle
dialog
implicite, - si on l’ouvre avec la méthode
showModal()
:- il a une propriété
aria-modal="true"
implicite, - il peut être fermé avec la touche Échap,
- il a une propriété
- il piège le focus en son sein — mais permet d’atteindre la fenêtre du navigateur, c’est toujours discuté…
- il restaure le focus à l’élément qui a déclenché l’ouverture, lors de sa fermeture,
- il rend le reste du document
inert
automatiquement.
Mais il y a plus ! Voyez plutôt :
- Le pseudo-élément
::backdrop
permet de styler l’arrière-plan superposé vraiment facilement. - La pseudo-classe
:modal
s’applique lorsque<dialog>
est ouvert avec la méthodeshowModal()
. - Si votre boîte de dialogue contient un formulaire, utiliser l’attribut
method="dialog"
sur le formulaire permet à votre bouton de soumission de fermer la boîte de dialogue en transmettant les données.
L’élément <dialog>
seul n’est pas (encore) suffisamment cohérent entre les différents navigateurs et technologies d’assistance, comme Scott O’Hara (de nouveau) l’a remarqué, mais vous avez saisi le principe : qu’en serait-il si on l’enrichissait en appliquant le motif de conception ARIA dialog, et en s’appuyant sur le comportement natif pour économiser quelques lignes de JavaScript ?
C’est plus ou moins ce qu’Adam Argyle a exploré avec son composant dialog sur web.dev avec quelques astuces sympathiques à apprendre — gardez cependant à l’esprit que les contenus sur web.dev ne sont pas testés avec des technologies d’assistance ni contre les WCAG.
Construire un composant dialog n’est vraiment pas évident, et Kitty Giraudel a détaillé ce dont vous avez besoin pour faire un bon composant dialog. Depuis la rédaction de ces articles, le support de <dialog>
s’est considérablement amélioré et fait même partie d’Interop 2022, donc attendez-vous à ce que le support s’améliore encore en ces derniers jours de 2022.
C’est probablement l’exemple le moins évident, puisqu’en parlant d’amélioration progressive l’élément <dialog>
pourrait être un mauvais choix : il ne peut tout bonnement pas fonctionner sans JavaScript. Mais si votre JavaScript est en panne pour une raison inopinée, vos écouteurs d’événement pourraient toujours fonctionner.
Conclusion
HTML est incroyable. Ça n’est pas suffisant pour proposer un expérience accessible à tous les utilisateurs, comme Dave Rupert l’a mis en exergue il y a deux dans HTML: the inaccessible parts — bien que certains de ces exemples ne sont plus d’actualité, corrigés dans les navigateurs ou technologies d’assistance.
Mais ne pas être parfait est probablement toujours mieux qu’être neutre, n’est-ce pas ?
Je crois que c’est le genre de choses qu’HTML permet : <details>
et <summary>
finiront par être implémentés et restitués de façon cohérente aux technologies d’assistance, rendant les enrichissements avec ARIA caduques. Le travail de Scott, du test très avancé aux articles de blogs et à l’ouverture de tickets de bug, est la voie à suivre. Les implémentations complètes dans les bibliothèques comme a11y-dialog de Kitty Giraudel permettent de gagner en maturité et de clarifier les attentes pour ces composants. Et avec l’augmentation des usages, les navigateurs et technologies d’assistance vont certainement reconsidérer leurs priorisations, dans des opérations comme Interop ou ARIA-AT.
Alors utilisons, testons, et aidons les navigateurs et technologies d’assistance à supporter ces nouveaux éléments HTML !
Laisser un commentaire