Documentation RGAA

Cette page renseigne des règles à suivre concernant l'Accessibilité.
RGAA signifie Référentiel Général d’Amélioration de l’Accessibilité

Annotation

Comment mettre en place une annotation en bas de page ? Critère 10-9 Annotation

Une annotation doit faire référence à sa destination.

  • Invalide

    Ici l'ancre liée à l'annotation n'est pas cliquable, le contenu est difficilement accessible.

  • Valide

    Pour mettre en place une annotation valide il y a plusieurs cas possibles :

    1. Avoir l'annotation placée juste avant le contenu
    2. (ex: champ obligatoire dans les formulaires)
    3. Utiliser des ancres pour faire le lien entre l'annotation et sa "référence".

    Une ancre est cliquable et amène à l'annotation. Le contenu de celle-ci est facilement accessible et une ancre permet de revenir à l'endroit initial où celle-ci était signalée.

    Une ancre reliée à une annotation :


    Plusieurs ancres reliées à une même annotation :

Attribut autocomplete

Critère 11.13

Attribut autocomplete.

Pourquoi mettre en place l'atttribut autocomplete :

  • Permettre aux navigateurs de remplir automatiquement le champ à la place de l'utilisateur
  • Ajoute un élément différenciant sur les champs de formulaire, cela pourra servir pour un outils tier, la mise en place de css...
  • Invalide

    • L'information demandé ne concerne pas l'utilisateur :
      • Le prénom du l'utilisateur
      • Le prénom du conjoint de l'utilisateur
    • Une double valeur, exemple la ville + le code postale de l'utilisateur

    Soit ne pas renseigner l'atttribut autocomplete soit le renseigner avec off

  • Oui

    Pour des valeurs comme nom / prénom / date d'anniversaire / code postale... (pour la liste exhaustisve voir avec UX) glossaire autocomplete

    Cas particuliers : le combobox

    Le combobox proposant aussi une aide à la saisie, il peu y avoir conflit. Pour éviter cela, la valeur de l'autocomplete sera dynamique.

    A l'initialisation de la page :

    A la prise de focus sur le champ :

Iframe

Comment structurer correctement une <iframe> ?

  • Invalide

    Voila le code d'une iframe fournie par youtube

  • Valide

    Pour qu'une iframe soit valide, il faut qu'elle ait un attribut title. Critère 2 MDN

    Certains éléments fournis dans les iframe ne sont pas corrects.

    L'attribut title doit être explicite. Dans notre cas il faut indiquer le nom de la vidéo. L'usage de certains attributs n'est pas correct.

    Exemple : frameborder ne doit pas être utilisé car il est déprécié. Il est aussi préférable de gérer la taille de l'iframe via css

Images

Image décorative (à faire ignorer par les lecteurs d'écran)

Cas général

L'attribut alt doit être renseigné à vide.


Cas pour le SEO (référencement Naturel)

L'attribut alt doit être renseigné avec un texte optimisé pour le SEO.
Il est nécessaire d'ajouter l'attribut aria-hidden='true' pour permettre aux lecteurs d'écran d'ignorer l'image.

Image non décorative (porteuse de sens/d'information illustrant le propos de la page)

L'attribut alt doit être renseigné avec un texte porteur d'informations.

Images Légende

  • La légende d'une image peut contenir :

    • un texte associé
    • et/ou
    • un crédit photo
  • Exemple de rendu :

    Texte à renseigner
    Texte légende de notre image© Crédit Photo

Image décorative ou non décorative avec une légende

A partir du moment où une image comporte une légende :

  • la balise html figure doit être utilisée pour englober à la fois l'image & sa légende.
    • on doit lui adjoindre un role='figure' .
    • un attribut aria-label doit être renseigné et correspondre à la valeur du figcaption , c'est à dire soit le :
      • texte légende + crédit photo (si les 2 sont renseignés)
      • texte légende (si seul)
      • crédit photo (si seul)
  • la balise html figcaption doit englober la légende.

Remarque :

Le altest obligatoire même si l'image est décorative, dans ce cas indiquer par exemple "illustration" dans le alt si la légende n'apporte pas d'information pertinente (ex: copyright). Si il y a plusieurs images avec légende dans la page, incrémenter la valeur d"'illustration" = illustration 1, illustration 2. A adapter en fonction du contexte par le contributeur


Exemple de structure valide pour une image et sa légende :

Label et son champ de formulaire

Pourquoi et comment utiliser l'association <label> et son champs de formulaire?

Le champ de formulaire peut être un :

  • input
  • textarea
  • select

Principes de base :

  • Le label doit être associé à un champ de formulaire et réciproquement. C’est à dire que l’un ne va pas sans l’autre.
  • Le label est utilisé uniquement dans un formulaire et sert à nommer un champ de formulaire.
  • Le label doit être pertinent et doit permettre de comprendre la fonction du champ auquel il est rattaché.
  • Le label ne doit pas être utilisé pour afficher un simple texte.

L'intitulé du Label doit être pertinent & explicite :

  • pas d’abréviation
  • pas de jargon ou de vocabulaire trop spécifique
  • ne doit pas être trop long

Comment utiliser correctement un label ?

Pour associer correctement votre label et votre champ input par exemple, nous allons utiliser l'attribut for :
Pour associer correctement votre input et votre champ label, nous allons utiliser l'attribut id :

Lien ou bouton

Comment choisir entre <a> et <button> ?

Est-ce que l’élément interactif redirige vers une nouvelle page (changement d’url), ou navigation dans la page (ancre) ?

  • Non (utiliser un élément button)

    Un button déclenche une action, il est par exemple employé pour :

    • soumettre des informations
    • afficher l’élément suivant ou précédent dans un carrousel
    • ouvrir ou fermer une fenêtre modale
    • etc...

  • Oui (utiliser un élément a)

    Un a permet de naviguer. Il est employé pour :

    • pointer sur une autre page
    • pointer sur une zone précise de la page courante par l’intermédiaire d’un système d’ancre.

Lien d'évitement

Lien du RGAA : Critère 12.6  / Critère 12.7

Lien d'évitement

C'est quoi ? Pourquoi faire ?

Pour répondre aux besoins d'accessibilité (critères 12.6 et 12.7) des "liens d'évitements" sont nécessaires. Leurs objectifs est simplement de naviguer dans la page en évitant une partie du contenu (le contenu est séparé dans différentes zones).

Pour la zone de contenu principale (main) il faut obligatoirement prévoir un lien d'évitement (avec ou sans landmark sur cette zone).

Pour les autres zones il y a plusieurs assemblages possibles :

  • lien d'évitement
  • landmark
  • lien d'évitement + landmark

Nous préconisons la mise en place systématique des landmarks sur les différentes zones. Pour les liens d'évitements (en plus de celui vers la zone principale) c'est à voir avec les UX.

Liste des landmarks:

  • role='banner'
  • role='navigation'
  • role='main'
  • role='contentinfo'
  • role='search'

Solution technique

Le code est à placer comme premier élément du body.

Les liens ne sont visibles que via la prise de focus.

Prévoir un role='navigation' + un aria-label pour donner du contexte.

Il faut aussi prévoir des id sur nos landmarks pour bénéficier de la gestion d'ancre native.

Libellés lien

Est-ce que le lien contient du texte ?

  • Non

    Ajouter un libellé texte en masquage accessible si nécessaire , et continuer.

    Si le lien est basé sur une image <img>, ajouter le libellé dans l’attribut alt de l’image, et continuer.

VERIFICATION EXPERT

lien avec img:

sr-only :

Est-ce que je peux déterminer la cible du lien uniquement à partir du libellé texte ?

Exemple : plusieurs liens “en savoir plus” sur une même page. Chaque lien possède une cible différente.

Est-ce que le contexte du lien permet de déterminer la cible du lien ?

Exemple :

  • Le contenu du paragraphe (<p>) dans lequel le lien texte est présent ;
  • Le contenu de l’item de liste (<li>) dans lequel le lien texte est présent ;
  • Le contenu du titre (<hx>) précédent le lien texte ;
  • Le contenu de la ou les cellule(s) d’en-tête de tableau (balise(s) <th>) associée(s) à la cellule de donnée (balise <td>) dans laquelle le lien texte est présent ;
  • Le contenu de la cellule de donnée (balise <td>) dans laquelle le lien texte est présent.
  • Non

    Ajouter une information discriminante au libellé texte, par une des techniques

  • Oui

    Terminé

sr-only :

aria-label :

aria-describedby :

title :

Libellés button

Est-ce que le bouton possède un libellé texte ?

  • Non

    Ajouter un libellé texte en masquage accessible si nécessaire , et continuer.

    Si le lien est basé sur une image <img>, ajouter le libellé dans l’attribut alt de l’image, et continuer.

VERIFICATION EXPERT

button avec img:

sr-only :

Est-ce que je peux déterminer l’action portée par le bouton uniquement à partir du libellé texte ?

Exemple : plusieurs boutons “supprimer” sur une page listant des options.

  • Non

    Ajouter une information discriminante au libellé texte, par une des techniques

  • Oui

    Terminé

sr-only :

aria-label :

aria-describedby :

title :

Placeholder

Critère RGAA : 11.10.5

Comment utiliser correctement un placeholder ?

  • Invalide

    Le placeholder ne doit jamais contenir d’information importante (exemple : précision nécessaire à la compréhension de la demande, format de donnée), ce sont les sous-labels (indications de saisie) qu’il faut utiliser.

  • Valide

    le placeholder peut contenir des exemples de saisie non obligatoires à la compréhension (exemple : des noms de produits dans une barre de recherche d’un site e-commerce)

    La bonne pratique serait de ne pas afficher de placeholder par défaut, et ne les utiliser que s’ils apportent quelque chose dans l’expérience utilisateur sans être indispensables à restituer.

    A noter :

    • Un placeholder n'est ni un label, ni un message d’aide.
    • Tous les lecteurs d’écran ne les restituent pas
    • Le placeholder est sujet aux mêmes règles de contraste qu’un texte (4,5:1).

Structure bouton complexe

Comment bien structurer un bouton dit complexe

  • Invalide

    Pour l'accessibilité cette structure est invalide car un button n'accepte que des balises de type : contenu phrasé.
    Une div n'est pas un contenu phrasé

  • Valide

    Le span est une balise de contenu phrasé.
    Dans ce cas de figure c'est la balise la plus adaptée.

Structure input / label

Comment bien associer son champ de formulaire <input> et son <label> ?

  • Informations

    • Il est nécessaire d'englober le label et son champ de formulaire dans une classe .form-group
    • Le labeldoit être associé à la classe .field-label
    • Si le champ est obligatoire alors il doit comporter l'attribut required

    Invalide

    Ici mon label et mon input ne sont pas liés.

  • Valide

    Pour relier mon label.field-label et mon input j'utilise les attributs foret id .

    l'attribut name doit également être renseigné et correspond au nom du champ qui sera rattaché à la donnée récupérée via le formulaire.

Structure input / label / sous-label

Comment bien associer son champ de formulaire avec son label et sous-label ?

  • Un champ de formulaire peut être rattaché un label et un sous-label.
    Nous avons déjà vu juste au dessus comment mettre en place le label.
    Pour ajouter un sous-label il faut utiliser la balise html p associée à la classe .field-item.

    Invalide

    Ici il n'y a que mon label qui est rattaché à moninput .

  • Valide

    Pour relier mon sous-label p.help-input je lui attribue un id et sur mon champinputje mets en place l'attribut aria-describedby .

    Le .field-label et le .help-input sont reliés à mon input .
    Lors de la lecture du champinput les 2 éléments seront vocalisés.

Structure champ regroupé

Dans quel cas de figure mettre en place un champ de type regroupé

  • Avec des champs de type radio (min 2)
  • Avec des champs de type checkbox (min 2). Dans le cas avec un seul checkbox pas de structure regroupé
  • Avec plusieurs champs se rapportant à la même question (min 2). Exemple : 3 champs texte pour renseigner un date ou j'ai plusieurs bénéficiaire (personne A et B) et des questions identiques (prénom / nom)

Plusieurs solutions technique

Il y a plusieurs structure disponible pour mettre en palce un champ regroupé :

  • Structure native avec les balises : fieldset legend
  • Structure aria avec des attributs comme : role="radiogroup" role="group"

Nous avons fait le choix de la structure aria qui est plus souple que la structure native.

Quelle structure appliqué ?

  • Invalide

    Les différents éléments ne sont pas techniquement reliés entre eux.

  • Valide

    Pour une structure valide il est obligatoire d'avoir role="radiogroup" ou role="group" et de lui relier notre question, ici .field-label via id et aria-labelledby.

    Pour la structure label avec input (cf structure-input-label)

Structure champ regroupé complexe

Pourquoi complexe ?

Il est possible d'avoir des informations complémentaire dans nos champs regroupés. La structure va donc évoluer, certains éléments devront être techniquement reliés.

Les nouveautées :

  • Ajout d'un .help-input
  • Ajout d'un .information
  • Ajout d'un .action-modal

Quelle structure appliqué ?

  • Invalide

    Les différents éléments ne sont pas techniquement reliés entre eux.

  • Valide

    Pour une structure valide il est obligatoire de relier notre .help-input via id et aria-labelledby à notre role="radiogroup" ou role="group".

    Dans le cas avec .information ou .action-modal nous allons avoir une modal ou collapse avec un button comme élément déclencheur. L'élément est focusable, grâce à cela peu importe la manière de naviguer avec les AT, l’utilisateur va le lire et donc pas besoin de lié les éléments. Néanmoins les règles de construction d'un button s'applique (cf libelles-bouton)

Structure combobox

Qu'est-ce qu'un champ combobox / autocomplete ?

Le piège :

Tout d'abord ne pas confondre l'attribut autocomplete et un composant combobox.

L'attribut autocomplete permet à votre navigateur de proposer une autocompletion alors qu'un composant combobox va proposer une autocompletion avec un service extérieur (ex: une api pour retrouver son addresse).

La solution technique, partie HTML :

  • Utilisation d'un champ de saisie texte standard input ou textarea avec :
    • role='combobox'
    • aria-autocomplete='list'
    • aria-expanded='true/false'
    • autocomplete="XXX" (pour plus d'info sur la valeur à choisir doc attribut-autocomplete)
  • Une liste ul/ol pour la présentation des propositions avec :
    • role='listbox'
    • aria-label='Suggestions de saisie : (contexte différenciant)'
  • Chacune des propositions seront dans un li avec :
    • role='option'
    • aria-selected='true/false'
    • tabindex='-1'
  • Un compteur de résultat sera présent, le texte sera injecté via js dans une div avec :
    • aria-atomic='true'
    • aria-live='polite'

La solution technique, partie JS :

  • Gestion de la valeur aria-expanded='true/false' à l'ouverture/fermeture de la liste de résultat
  • Incrémentation du compteur en fonction du nombre de résultat, uniquement quand la liste de résulat avec visible
  • Navigation entre les résultats via les flèches directionnelles haut/bas
    • Replacement du focus sur le résultat current
    • Gestion de la valeur des aria-selected='true/false'
  • La solution de gestion via aria-activedescendant n'a pas été retennu car moins robuste que la solution avec un focus natif
  • Lors de la navigation, il est possible de reprendre la saisie (sans action supplémentaire)
  • Une tabulation fera sortir le focus du champ et entrainera la fermeture de la liste de résultat
  • La selection d'un résultat s'effectura via la touche enter ou un click
    • Fermeture de la liste de résultat
    • Retour du focus dans le champ de saisie
    • Mise à jour de la valeur du champ de saisie avec le résultat choisi

Structure lien / bouton

Critère du RGAA : Liens Critère 10-6 Critère 10-7

Comment coder un <a> et <button> accessible ?

Principes de base :

Un cas d'exception : mon lien / bouton se trouve dans une zone de texte.

Dans ce cas de figure je dois appliquer une représentation graphique différenciante (exemple: le soulignement)

Si ma représentation graphique différenciante est uniquement portée par une couleur alors je dois appliquer les 3 critères suivant (10-6):

  • un contraste d'au moins 3:1 entre le texte normal et le lien / bouton
  • une indication visuelle autre que la couleur, au hover
  • une indication visuelle autre que la couleur, au focus

Structure lien complexe

Comment bien structurer un lien dit complexe

  • Invalide

    Pour l'accessibilité cette structure est invalide car le libellé est l'ensemble du contenu de la balise a. Le libellé n'est pas explicite, il y a trop d'information.

  • Valide

    Ici le lien à un libellé moins dense. Il est plus simple d'avoir un libellé explicite. Pour répondre aux besoins UX/UI d'avoir une zone de clic plus grande comme avec le code invalide, on peut utiliser la méthode du lien étendu (streched link).

Structure notification

Comment mettre en place un système de notification ?

Principes de base

  • Les notifications sont persistantes (pas de limite de temps)
  • Les notifications seront gérées dans un centre de notification .wrapper-notification
    • role='region'
    • aria-label='Indique le nombre de notification' (gestion dynamique)
    • S'il n'y a pas de notification, le .wrapper-notification n'est pas dans le DOM. Il est injecté en même temps que la notification.

Comportement :

  • Ajout d'une notification
    • Si le focus est déjà positionné dans la zone de notifications :
      • Le focus n'est pas déplacé
      • Le compteur de notification est mis à jour : aria-label
    • Si le focus n'est pas positionné dans la zone de notifications :
      • Le focus est déplacé sur la nouvelle notification
      • Le compteur de notification est mis à jour : aria-label
  • Fermeture d'une notification
    • Replacement du focus
      • Soit repositionner le focus sur l'élément déclencheur
      • Soit repositionner le focus sur l'élément permettant une bonne reprise de la navigation (main, h1, barre d'étape)
      • Le replacement du focus peut changer en fonction de la navigation de l'utilisateur. Si l'utilisateur sort du centre de notification, alors le retour prévu sur l'élément déclencheur change.
        • S'il y a plusieurs notifications, le focus est placé sur le centre de notification.
        • Si c'est la dernière notification, le focus est replacé sur la balise main.
    • Le compteur de notification est mis à jour : aria-label
      • Lorsqu'il n'y a plus de notification, .wrapper-notification est supprimé du DOM.

Un exemple valide de structure pour la mise en place d'une notification

Structure message erreur

Comment mettre en place un message d'erreur sur un élément de formulaire ? (non regroupé)

  • Le message d'erreur doit être situé après le champ de formulaire et doit être explicite.
  • Le message d'erreur doit être relié via l'attribut id et l'attribut aria-describedby qui lui, doit être renseigné sur le champ input .
  • Il est nécessaire d'ajouter l'attribut aria-invalid='true' pour bien signifier que le champ input est en erreur.
  • Une classe .has-error est associée à la classe .form-group .
  • Une classe .help-block est ajoutée à la balise p contenant le message d'erreur.

Attention, en plus de la structure suivante, il est nécessaire de gérer le placement du focus dans le champ avec l'apparition du message d'erreur.

Voici un exemple valide de structure pour la mise en place d'un message d'erreur

Structure message erreur (champ regroupé)

Comment mettre en place un message d'erreur sur un élément de formulaire ? (champ regroupé)

  • Le message d'erreur doit être situé après le champ de formulaire et doit être explicite.
  • Le message d'erreur doit être relié via l'attribut id et l'attribut aria-labelledby qui lui, doit être renseigné sur l'élément role='group' ou role='radiogroup'.
  • Pour le placement du focus lors de la déclaration de l'erreur 2 options possibles :
    • Un tabindex='-1' est placé sur l'émément portant le role='group / radiogroup'.
    • Directement sur le 1er input du groupe (plus simple à mettre en place et moins verbeux, préconisation maif)
  • Une classe .has-error est associée à la classe .form-group .
  • Une classe .help-block est ajoutée à la balise p contenant le message d'erreur.
  • La mise en place d'un aria-invalid n'est pas nécessaire. La structure actuelle couvre le critère 11.10

Voici un exemple valide de structure pour la mise en place d'un message d'erreur

Modal

Quel comportement doit avoir une modal accessible ?

  • À l'ouverture de la modale, le focus est déplacé pour continuer la lecture avec le contenu de la modale.
  • Après l'ouverture, le focus doit être limité aux éléments à l'intérieur de la modale.
  • La fermeture s'effectue soit via un element button présent dans la modale, soit via la touche echap du clavier.
  • À la fermeture de la modale, le focus est placé sur l'élément ayant permis son ouverture.
  • Quand la modale est fermée, elle ne doit pas être lisible.

Quelle structure HTML permet d'avoir une modale accessible ?

  1. Conteneur principal
    • role='dialog'
    • Un lien technique avec le titre aria-labelledby='id_Titre'
    • Permettre le placement de focus avec un tabindex='-1'
    • aria-modal='true'
  2. Conteneur secondaire
    • role='document'
  3. Conteneur .modal-content
    1. Conteneur .modal-header
      • S'il y a un bouton de fermeture, il doit être positionné en première position dans le conteneur role='document'.
      • Le titre doit être dans une balise sémantique adaptée de préférence h1, la modale représente un nouveau contexte le h1 est plus cohérent. Néanmoins il est possible d'avoir un autre niveau de titre. Ne pas oublier l'id pour le lien technique avec aria-labelledby
    2. Conteneur .modal-body (RAS)
    3. Conteneur .modal-footer (RAS)

Structure picto

Le picto via HTML

  • Principes de base :

    Utilisation de la balise <i>. La balise <span> est plus adaptée mais dans notre contexte il est préférable de garder une balise facilement identifiable.

    Nos icones ne sont pas porteuses d'information, il faut donc ajouter aria-hidden='true'pour que le lecteur ne vocalise par le picto.

  • Structure :

Le picto via les pseudo-éléments en CSS (&::before et &::after)

  • Principes de base :

    La mixin svg-sprite-icon permet de générer les pictos avec un mask-image.

    L'intéret est que le lecteur d'écran ne vocalise pas d'information contrairement à la solution via une font d'icones. En passant par une font le lecteur d'écran peut chercher à vocaliser l'id $id et cela n'aurait aucun sens pour l'internaute.

  • Structure invalide :

    Structure valide :

    La variable $id renseigne maintenant le mask-image et non l'attribut content qui lui reste vide.

Structure contenu

Un contenu de type texte doit toujours être placé dans une balise sémantique

  • Invalide

  • Valide