Il n'y a pas de résultat pour cette recherche

85 résultats de recherche (8 résultats par page - 11 pages)

  • Liste de suggestions accessible — 18 03 2025

    Illustration de l'utilisation de la balise HTML5 <datalist>

    recueil liste-de-suggestions-accessible /recueil/datalist/

    Introduction

    L'élément HTML <datalist> contient un ensemble d'éléments <option> qui représentent les valeurs possibles pour d'autres contrôles.
    Nativement accessible, plus besoin de librairie JavaScript pour faire une liste de suggestions si vous êtes prêt à faire une croix sur la personnalisation graphique.
    J'ajoute un petit script pour les lecteurs d'écran afin de faciliter son usage.

    Code

    <label for="ice-cream-choice">Choose a flavor:</label>
    <input 
           list="ice-cream-flavors" 
           id="ice-cream-choice" 
           name="ice-cream-choice" 
           autocomplete="off"
           />
    <p id="suggestions-help" role="status" aria-live="polite" class="visually-hidden"></p>
    
    <datalist id="ice-cream-flavors">
      <option value="Chocolate"></option>
      <option value="Chocolate White"></option>
      <option value="Dark Chocolate"></option>
      <option value="Coconut"></option>
      <option value="Mint"></option>
      <option value="Strawberry"></option>
      <option value="Vanilla"></option>
    </datalist>
    .visually-hidden {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip: rect(0, 0, 0, 0);
      white-space: nowrap;
      border-width: 0;
    }
    const inputField = document.getElementById("ice-cream-choice");
    const datalist = document.getElementById("ice-cream-flavors");
    const help = document.getElementById("suggestions-help");
    
    function hasCommonSubstring(str1, str2) {
      return str1.includes(str2) || str2.includes(str1);
    }
    
    inputField.addEventListener("input", () => {
      let value = inputField.value;
      let options = datalist.options;
      let suggestionsCount  = 0;
    
      for (let i = 0; i < options.length; i++) {
        if (
          hasCommonSubstring(value.toLowerCase(), options[i].value.toLowerCase())
        ) {
          suggestionsCount++;
        }
      }
      if (suggestionsCount > 0 && suggestionsCount < options.length ) {
        help.textContent=`There are ${suggestionsCount} suggestions. Use the up and down arrows to browse.`;
      }
    });

    Rendu

  • Allegretto — 17 01 2024

    Application de gestion de planning d'occupation

    realisations allegretto /realisations/allegretto/

    Projet de calendrier décentralisé pour la gestion d'une résidence familiale

    • Pas d'inscription : seule la personne ajoutée par l'admin on l'accès à l'outil
    • Le mot de passe créé par l'utilisateur est sécurisé et indéchiffrable
    • Les utilisateurs sont regroupés par famille
    • L'ajout d'une demande de séjour se fait par famille, un mail de notification est envoyé
    • Un membre donne son accord au nom de sa famille
    • Les séjours en attendent de validation sont en gris sur le calendrier et passe en vert quand tout le monde est ok

    Sources : https://github.com/pierretl/allegretto

    Le logo est une vectorisation du logo dessiné par mon grand-père.

    UI Design

    Version 2 — 17/01/2024

    Sass de connexion
    • Ajout du parcours mot de passe oublié
    • Redesign du site
    • Refonte UX de l'interface
    • Amélioration de l'affichage sur mobbile
    • Affiche la liste uniquement si le séjour concerne la famille de l'utilisateur
    • Personnalise la couleur de la date du jour
    • Les séjours dons la date de départ est passé s'affiche sur un fond gris
    Tableau de bord des séjours
    Administration des utilisateurs
    Tableau de bord des séjours sur smartphone
    Administration des utilisateurs sur smartphone

    Version 1 — 22/009/2022

    Sass de connexion
    • Pas d'inscription : seule la personne ajoutée par l'admin on l'accès à l'outil
    • Le mot de passe créé par l'utilisateur est sécurisé et indéchiffrable
    • Les utilisateurs sont regroupés par famille
    • L'ajout d'une demande de séjour se fait par famille, un mail de notification est envoyé
    • Un membre donne son accord au nom de sa famille
    • Les séjours en attendent de validation sont en gris sur le calendrier et passe en vert quand tout le monde est ok
    Tableau de bord des séjours
    Administration des utilisateurs
  • Gulp V4 : compiler Sass et les fichiers JS — 06 06 2023

    Configuration de Sass, JS et BrowserSync avec Gulp V4

    recueil gulp-v4-:-compiler-sass-et-les-fichiers-js /recueil/gulp/
    1. Vérifier que vous avez Node.js

      node -v

      puis de npm avec

      npm -v

      Sinon télécharger et installer Node.js

    2. Installer gulp
      npm install gulp-cli -g

      gulp -v pour connaitre la version installer

    3. Initialiser un nouveau projet
      npm init -y

      Un fichier package.json

      est créer
    4. Installation de ce qui est nécessaire

      npm install --save-dev gulp gulp-sass browser-sync gulp-autoprefixer gulp-clean-css gulp-sourcemaps gulp-mode gulp-concat gulp-rename gulp-uglify
    5. Créer le fichier gulpfile.js à la racine du projet

      const gulp =  require('gulp');
      const sass = require('gulp-sass')(require('sass'));
      const prefix = require('gulp-autoprefixer');
      const minify = require('gulp-clean-css');
      const sourcemaps = require('gulp-sourcemaps');
      const mode = require('gulp-mode')();
      const browserSync = require('browser-sync').create();
      const concat = require('gulp-concat');
      const rename = require('gulp-rename');
      const uglify = require('gulp-uglify');
      
      
      // compilation des styles CSS
      function styles(){
          // Emplacement des fichiers .scss
          return gulp.src('./_scss/style.scss')
          // Source map
              .pipe(mode.development( sourcemaps.init() ))
          // Passer ces fichiers au compilateur + si erreur affiche les log
              .pipe(sass().on('error', sass.logError))
          // Préfixer automatiquement les propriétés nécessaire
              .pipe(prefix('last 2 versions'))
          // Minifier
              .pipe(minify())
          // Source map
              .pipe(mode.development( sourcemaps.write() ))
          // Emplacement du fichier .css généré
              .pipe(gulp.dest('./style/'))
          // changements de flux pour tous les navigateurs
              .pipe(mode.development( browserSync.stream() ));
      }
      
      // compilation des scripts JavaScript
      function scriptJs(){
          return gulp.src('./js/*.js')
              .pipe(concat('script.js'))
              .pipe(rename({suffix: '.min'}))
              .pipe(uglify())
              .pipe(gulp.dest('./'))
              .pipe(mode.development( browserSync.stream() ));
      }
      
      // watch
      function watch() {
          browserSync.init({
              server: {
                  baseDir: './'
              }
          });
          gulp.watch('./_scss/**/*.scss', styles);
          gulp.watch('./*.html').on('change', browserSync.reload);
          gulp.watch('./js/**/*.js', scriptJs);
      }
      
      // Compilation des styles pour la prod
      function buildScss(){
          // Emplacement des fichiers .scss
          return gulp.src('./_scss/style.scss')
          // Passer ces fichiers au compilateur + si erreur affiche les log
              .pipe(sass().on('error', sass.logError))
          // Préfixer automatiquement les propriétés nécessaire
              .pipe(prefix('last 2 versions'))
          // Minifier
              .pipe(minify())
          // Emplacement du fichier .css généré
              .pipe(gulp.dest('./style/'));
      }
      
      
      exports.watch = watch;
      exports.build = gulp.series(buildScss, scriptJs);
    6. gulp build pour la production
      gulp watch pour la dev
  • Mode sombre et mode claire — 02 06 2023

    Mettre correctement en place un mode sombre/clair aussi appeler dark/light mode ou mode nuit/jour

    recueil mode-sombre-et-mode-claire /recueil/mode-sombre-et-mode-claire/

    CSS

    1. Utiliser les propriétés personnalisées (custom properties en anglais) pour gérer vos couleurs
      Donné un nom fonctionnel ou plus simplement numérote vos couleurs !

      body {
          background:var(--color1);
          color:var(--color2);
      }
    2. Créer le thème par défaut dans :root

      Mode clair par défaut

      :root {
          --color1:white;
          --color2:black;
          --color3:#F2F2F2;
      }

      Mode sombre par défaut

      :root {
          --color1:#222;
          --color2:#FFF;
          --color3:#555;
      }
    3. Définissez le jeu de couleurs du navigateur avec la propriété color-scheme ;

      Lorsqu'un utilisateur sélectionne un de ces jeux de couleurs, le système d'exploitation fait des ajustements à l'interface utilisateur. Cela comprend les contrôles de formulaires, les barres de défilement et les valeurs utilisées par le système de couleurs CSS.

      Mode clair par défaut

      :root {
          --color1:white;
          --color2:black;
          --color3:#F2F2F2;
          color-scheme: only light;
      }

      La valeur only sert à désactiver le remplacement de couleur du mode nuit du moteur de rendu Blink

      Mode sombre par défaut

      :root {
          --color1:#222;
          --color2:#FFF;
          --color3:#555;
          color-scheme: dark;
      
      }
    4. Créé le thème équivalent pour l'autre mode

      Mode clair par défaut

      .dark {
          --color1:#222;
          --color2:#FFF;
          --color3:#555;
          color-scheme: dark;
      }

      Mode sombre par défaut

      .light {
          --color1:white;
          --color2:black;
          --color3:#F2F2F2;
          color-scheme: only light;
      }

    JavaScript

    1. let root = document.querySelector(":root");
    2. Détecter la préférence de l'utilisateur

      Mode clair par défaut

      if (
          window.matchMedia &&
          window.matchMedia("(prefers-color-scheme: dark)").matches
      ) {
          root.classList.toggle("dark");
      }

      Mode sombre par défaut

      Comme dans la grande majorité des cas, le thème clair n'est pas demandé (car par défaut), je conserve le thème sombre du site

    3. Détecter le changement de préférence utilisateur

      Mode clair par défaut

      window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
          if(e.matches) {
              root.classList.add("dark");
          } else {
              root.classList.remove("dark");
          }
      });

      Mode sombre par défaut

      Pas de détection non plus

    4. Basculer de mode à tout instant en une action

      Mode clair par défaut
      document.querySelector("button").addEventListener("click", () => {
          event.preventDefault();
          root.classList.toggle("dark");
      });
      Mode sombre par défaut
      document.querySelector("button").addEventListener("click", () => {
          event.preventDefault();
          root.classList.toggle("light");
      });
    5. Je recommande de sauvegarder dans le localStorage tout changement de mode afin de pouvoir le configurer lors de la prochaine visite

    Démonstration

    Basculer en mode sombre

    Mode sombre par défaut

  • Outils d’Accessibilité Web — 01 06 2023

    Quelques outils pour mettre en évidence des soucis d'accessibilité

    recueil outils-d'accessibilite-web /recueil/outils-accessibilite/

    Seuls les liens des extensions Firefox sont répertoriés parce que ce navigateur fait partie des environnements de test officiels à la différence de Chrome.

  • Modèle BUSES — 31 05 2023

    Ensemble de concepts et de bonne pratique pour organiser et maintenir du SCSS

    recueil modele-buses /recueil/buses/

    Introduction

    La modèle BUSE est un ensemble de principe de conception, de regle d'usage et d'organisation afin de mettre en place du code SCSS maintenable.
    L'ensemble de ses règles n'est pas immuable et doit être adapté à vos besoins.
    Les cas fondateurs du modèle

    Un nom mémotechnique

    • Base : Function, mixin, variable, reset
    • Utilitaire : Les éléments de base réutilisable et partageable
    • Structure : Les squelettes responsive sans le contenu
    • Element : Spécificité d'un usage
    • Satellite : Les bibliothèques externes et leurs surcharges

    Principe de conception de l'architecture

    • Avoir une arborescence simple et compréhensible par tous
    • Appliquer des règles de nomenclature et les respecter
    • Décider de tout cela avec son équipe, les impliquer

    Arborescence

    _sass
        1-Base
        2-Utilitaire
        3-Structure
        4-Element
        5-Satellite
        style.scss

    Les dossiers principaux

    L'ensemble des fichiers SCSS doit être regroupé et classé dans des répertoires
    Préfixé chaque dossier par une numérotation afin de les faire apparaitre dans un ordre logique : du plus abstrait au plus spécifique

    Chacun de ses répertoires possède un fichier index nommé __index.scss
    Le double undersore permet que le fichier se retrouve toujours en haut de l'arborescence.

    _sass
        2-Utilitaire
            __index.scss
            _block.scss
            _bouton.scss
            _espacement.scss
            _flex.scss
            _text.scss
            _z-index.scss

    L'index sert de fichier d'intermédiaire pour importer tous les fichiers ou les index des sous-dossiers à la racine de ce répertoire.
    Les imports sont classés par ordre alphabétique où par besoin quand c'est nécessaire
    Utiliser des sous-dossiers dès lors que deux fichiers ou plus aborde le même thème

    index d'un dossier Utilitaire
    @import 'block';
    @import 'bouton';
    @import 'espacement';
    @import 'flex';
    @import 'text';
    @import 'z-index';
    Classement par ordre alphabétique
    index d'un dossier Base
    @import 'breakpoint';
    @import 'couleur';
    @import 'taille';
    
    @import 'font';
    @import 'base';
    @import 'z-index';
    Classement par besoin
    index du dossier Base plus complexe
    @import 'Variable/_index';
    @import 'Function/_index';
    @import 'Mixin/_index';
    
    @import 'couleur';
    @import 'focus';
    @import 'font';
    @import 'base';
    Classement par besoin

    La langue

    Le français ou la langue maternelle de l'équipe :

    • On évite tous problèmes de mauvaises traductions
    • Le franglais est conseillé pour les mots francisés (pourriel par exemple) et pour des termes techniques (responsive, flex etc...)
    • Un jargon métier est difficilement traduisible
    • En cas de rachat, ça leur fera les pieds !
    • Si votre équipe est internationale on utilisera l'anglais, imposés quelque court de rafraichissement à vos équipes !

    Fichier a la racine

    La feuille de style qui comporte tous les imports nécessaires, style.scss

    @import '1-Base/_index';
    @import '2-Utilitaire/_index';
    @import '3-Structure/_index';
    @import '4-Element/_index';
    @import '5-Satellite/_index';

    Au même niveau, l'on peux ajouter des feuille spécifique, qui importerait tous les styles de texte et lien/bouton pour les appliques dans un éditeur WYSIWYG par exemple

    Bonne pratique

    Établir des règles

    Que l'on travaille seul où a plusieurs, il est essentiel d'établir des règles sans exception, pour ne pas à avoir à faire du cas par cas et a complexifié votre projet.
    Des règles sur la nomenclature de fichier, de dossier, de nom de classe, de type de sélecteur, de norme d'indentation et de tous ce qui vous semble utile, de chose que vous avait pu rencontrer par le passé et que vous ne souhaitez pas revoir !
    Idéalement il faut mettre tous ça par écrit, sur un page de votre style guide

    Bannir les imbrications

    Même si les imbrications peuvent faciliter la vie et que cette fonctionnalité est en working draft coté CSS, voir CSS Nesting Module
    Son abus ou son utilisation pour des composants complexes est inapproprié.
    Pour avoir une règle simple, mieux vaut l'interdire !

    Établir une convention de Nommage

    Utilisé une méthodologie existante ou faite en une a votre image : convention de nommage de BUSES

    Découpage en dossier

    À partir de deux fichiers traitant du même thème on, crée un sous-dossier avec un index

    CSS réinitialisation

    On n'utilise pas de CSS reset tout fait, on créé son propre fichier en fonction de son besoin.
    Beaucoup de réinitialisations ne sont plus à jour ou peuvent ajouter des contraintes

    Convention de nommage

    Un savant mélange de BEM et de OOCSS afin de gommer les imperfections

    • On n'utilise pas les imbrications
    • On n'utilise pas les id
    • On n'utilise pas de !important
    • On n'utilise pas les classes de style pour cibler un élément en JavaScript
    • On préfixe par js__ les classe pour le JavaScript
    • On travail en utilitaire
    • On utilise des sélecteurs à un seul niveau, __ pour un sous-élément
      .bouton { ... }
      .bouton__forme { ... }
      .bouton__icon { ... }
      <button class="bouton">
          <span class="bouton__forme">
              <img src="bouton__icon" alt="">
          </span>
      </button>
    • Les modificateurs d'un élément sont préfixé v-- (v pour variation)
      .bouton { ... }
      .bouton.v--actif { ... }
      <button class="bouton v--actif"></button>
    • On ne déclare que ce que l'on utilise
      Pas de fonction pour généré tout l'espacement possible en toutes les tailles, direction, point de rupture
    • On utilise les initiles des propriété et valeur pour faires les utilitaires des espacement, du flexbox et cssgrid
      .mt-2 pour marin-top de taille 2
      .df pour display:flex
      .ji-c pour justify-items: center;

    Quelques mauvaises expériences

    Mauvaises traductions

    Je comptais ajouter un nouveau composant réutilisable pour géré les cadre, lorsque je découvrir qu'il en existait déjà un mais il était nommé card. Hors cadre en anglais c'est frame
    Je pense qu'il y a confusion entre le sous-élément carte qui reprend une partie des propriétés d'un cadre.

    Imbrication sur des composants complexes

    En voulant changer la couleur de soulignement d'un lien actif sur un mega menu responsif, je suis tomber sur un fichier faisant plus de 300 lignes de code imbriqué, écris en BEM.
    Des &__item il y en avait des dizaines sans compter tous les états actif, hover, focus...
    Impossible de faire une simple recherche Ctrl + F

  • Performances du site — 27 05 2023

    Résultat du site sous différents outils d'analyse de performance et d'émissions de carbone

    recueil performances-du-site /recueil/performance-du-site/

    Sommaire

    Website Carbon Calculator

    Website Carbon Calculator
    Cette page est plus propre que 96% des pages Web testées
    Seulement 0,04 g de CO2 est produit chaque fois que quelqu’un visite cette page web.
    Cette page Web semble fonctionner sur énergie durable

    GTmetrix

    GTmetrix
    Note : A, performance : 100%, Structure : 100%, LCP : 357ms, TBT : 0ms, CLS : 0

    PageSpeed Insights

    PageSpeed Insights Mobile
    Performance : 100%, Accessibilité : 100%, Bonnes pratiques : 100%, SEO : 100%
    PageSpeed Insights Bureau
    Performance : 100%, Accessibilité : 100%, Bonnes pratiques : 100%, SEO : 100%
  • Quelques notes sur les thématiques du RGAA — 12 05 2023

    Découvrir l’accessibilité du Web au travers une prise de notes durant une formation

    recueil quelques-notes-sur-les-thematiques-du-rgaa /recueil/note-accessibilite/

    Le contexte juridique et technique

    Un droit fondamental

    Contexte

    13 décembre 2006 : Convention relative aux droits des personnes handicapées de l’ONU

    Signé par tous les États membres dons la France (le 18 février 2010)

    Incapacité physique, mentales, intellectuelle ou sensoriel

    C'est le manque d'adaptation qui crée la situation de handicap

    Différents types de handicaps physique et sensoriel

    • Visuel (contraste, tache, vision)
    • Cognitif (décodage, DYS)
    • Physique

    Polyhandicap : multiple handicap

    En accessibilité on ne cible pas par type de handicap (car il y en trop), mais par besoin

    L'universalité inclut l'accessibilité.
    Le W3C ce veut Universalité : matériel, logiciel, infra, langue, culture, localisation et aptitudes physique ou mentale

    Accessibilité c'est différent du référencement et de la performance, c'est même parfois contre-productif

    Les personnes en situation de handicap n'ont pas de possibilité de résoudre leur problème
    À ne pas confondre avec le handicap situationnel qui peut être résolu sans aide, par exemple si on est dans un milieu trop ensoleillé ou dans un véhicule qui bouge

    Pourquoi faire de l'accessibilité

    Le numérique, c'est une promesse d'inclusion

    • Faire des choses qui n'étaient pas faisables en autonomie
    • Parfois la seule méthode pour communiquer
    • Parler des personnes en situation de handicap
    • Respect de leur droit
    • Ne pas parler de «ça sert à tout le monde», car ils vont penser que c'est de l'amélioration alors que l'accessibilité entraine des contraintes

    Exemple de besoin

    • Navigation clavier (par forcement clavier dalleur, ça peut être des boutons au niveau de la tete)
    • Uniquement a la souris : dispositif qui déplace le curseur (eyes tracking pa exemple
    • Description élément visuel (aveugle, mal voyante)
    • Description audio (sourd, malentendant)
    • Naviguer à son rythme, maitrise son environnement (trouble psychique)
    • Personnalise l'affichage (couleur, taille police, police etc.
    • Perte acuité visuel, audition, mental
    • Appréhension technologique, peur de casser, faire mal

    Améliorer la participation des personnes handicapées à la société (enfin !) grâce à l’accessibilité numérique

    Technologie d'assistance, quel exemple : Plage braille, clavier mono manuel, headstick, eye-tracking, clavier visuel, lecteur écran, contacteur au souffle, trackball, contrôle par la pensée (à l'état de recherche) etc

    Norme et référentiel

    Norme

    • UAAG pour les agents utilisateurs (navigateur, lecteur d'écran) : affichage par le navigateur de l’info-bulle d’un lien à la souris et au clavier.
    • ATAG pour les outils d’édition de contenus (CMS) : alternatives aux boutons de mise en forme, production de contenus conformes.
    • WCAG pour les contenus web : alternatives aux éléments graphiques.
    • L’API ARIA pour les composants riches.

    Version du WCAG :

    • Avant la 2.1, pour les non voyant essentiellement
    • version 2.1 : basse vision, troubles cognitifs, difficultés d’apprentissage et DYS
    • version 2.2 : prévue pour début 2023

    Trois niveaux d'accessibilité WCAG

    • A : Accès à l’information et d’une utilisabilité de base : 80% des critères.
    • AA : Améliorations et la prise en charge de contextes particuliers
      (les couleur par exemple)
    • AAA : Ne peut pas s'appliquer à tous les types de contenus et de situations

    En France, le niveau légal requis est le double A (AA) : pour être conforme il faut que tous les critères A et AA applicable du référentiel, soient conformes.

    Il n’est pas recommandé de faire de la conformité au niveau AAA une politique générale pour des sites entiers parce qu’il n’est pas possible de satisfaire tous les critères de succès de niveau AAA pour certains contenus.

    Source WCAG (en anglais)

    Référentiel RGAA

    En France on a créé un révérenciel; donner une méthode opérationnelle pour vérifier que les WCAG sont bien respectées sans avoir à tout lire (rédaction indépendantes des technologies et souvent abstraites)

    C'est le RGAA

    • Évaluer la conformité à la norme.
    • Mesurer et attester.
    • Servir de socle technique à la réglementation.
    • Attention au risque d'obsolescence

    La version 4 du RGAA a été publiée en septembre 2019. Elle est venue mettre à jour et remplacer le RGAA 3.2017

    Conformité obligatoire (RGAA 100%) selon la législation française : (décret du 14 mai 2009)

    • Administration
    • Privé qui gère du public (transport, eau)
    • Culturel, social
    • Les entreprises privées dont le chiffre d’affaires excède 25 millions d'euros
    • Sanction administrative, jusqu'à 5000 €, prononcée chaque année lorsque le manquement perdure
    • Les délais de mise en conformité des sites existants ne peuvent excéder trois ans

    Critères et tests du RGAA

    Aménagement raisonnable

    « On entend par “aménagement raisonnable” les modifications et ajustements nécessaires et appropriés n’imposant pas de charge disproportionnée ou indue apportés, en fonction des besoins dans une situation donnée, pour assurer aux personnes handicapées la jouissance ou l’exercice, sur la base de l’égalité avec les autres, de tous les droits de l’homme et de toutes les libertés fondamentales. »

    Article 2 de la CRDPH.

    En d'autre termes, en cas de dérogation sur un cas particulier, il faudrait fournir tous de même une alternative
    Sauf si cette alternative représente elle aussi une charge disproportionnée
    Alors il faut pouvoir permettre à l'utilisateur de faire un signalement et de lui répondre dans un délai raisonnable

    Refus d'aménagement raisonnable est puni par l'article 225-2 du Code pénal
    La loi prévoit entre 3 et 5 ans d'emprisonnement et entre 45 000 et 75 000 euros d'amende.

    Images

    RGAA : Images

    Nom accessible

    Utiliser par les lecteurs d'écran, le nom accessible n'est pas toujours affiché (le alt par exemple)

    <img src="img.png"
             alt="2019 EESC Civil society prize Award ceremony 12 december 2019"
             aria-label="image"/>

    Le nom accessible de l'exemple sera : « image »

    En cas d’implémentation multiple, le nom accessible utilisera par ordre de priorité :

    1. aria-labelledby
    2. aria-label
    3. alt
    4. title
    5. Si aucune des attributs précédents est valide, il n'y aura pas de nom accessible attribué

    Images décorative

    • Pas d'information dans l'image ni de volonté d'en transmettre une
    • Une image peut comporter du texte sans que celui-ci soit à but d'informatif, elle peut être juste décorative pour habiller une section

    Bitmap

    • alt=""préféré cet attribut car natif
    • aria-hidden="true"
    • role="presentation"
    <img src="image.png" alt="" />
    <img src="image.png" aria-hidden="true"/>
    <img src="image.png" role="presentation"/>

    Vectorielles

    • aria-hidden="true" sur l’élément <svg>
    • Aucun des attributs suivants ne doit être présent : aria-label, aria-describedby, aria-labelledby, role="img", title
    • Les balises <title> et <desc> doivent être vides ou absentes
    <svg aria-hidden="true">
        …
    </svg>

    Images porteuses d’information

    Vérifier auprès du contributeur ou de ce qu'a fait le bloc quelle information il veut véhiculer

    Bitmap

    • alt renseigné, solution a privilégié
    • title
    • aria-label
    • aria-labelledby

    Ne pas cumuler les méthodes car ça peut être contre-productif
    aria-label écrasera le rendu de alt
    aria-labelledby écrasera le rendu de tous le reste !

    <img src="image.png" alt="2019 EESC Civil society prize Award ceremony 12 december 2019" />

    Vectorielles

    Il faut utiliser ses deux attributs sur l’élément

    • role="img"
    • aria-label contenant l’alternative de l’image
    <svg role="img" aria-label="Profil renseigné à 90%">
        …
    </svg>

    Un alternative existe, mais balise title n'est pas bien supporté, préféré la première version

    <svg role="img" aria-labelledby="title_svg">
        <title id="title_svg">Profil renseigné à 90%</title>
        …
    </svg>

    SEO

    • Mettre plein de mot clé dans l'altest une idée reçue, ça ne fonctionne pas
    • Si l'équipe SEO impose de mettre du contenu dans le alt, ajouter aria-hidden="true" pour que le texte ne soit pas interprété pour les utilisateurs
    <img src="" alt="Carte France Production Usine" aria-hidden="true" />

    Image map

    • alt sur l'img pour décrire sa fonction
    • alt sur chaque area
    <img src="" alt="Carte de France" usemap="#LIEUX" />
    <map id="lieux" name="LIEUX">
        <area href="regi42" alt="Alsace">
        <area href="regi53" alt="Bretagne">
    </map>

    Images description détaillée

    Description détaillée adjacente où bien lien adjacent
    Exemple : access42.net (description détaillée adjacente)

    Commme aria-label et aria-labelledby ne sont exploités que par les lecteurs d’écrans.
    La meilleure solution est de proposer une alternative (modal, nouvelle page ou afficher/masquer)
    Mettre un alt trés général puis le bouton «lire la description détaillée de l'infographie» par exemple

    <img src="img.png" alt="infographie" />
    <a href="description.html">Description détaillée de l'infographie</a>
    
    <img src="img.png" alt="infographie" />
    <button aria-expanded="false">Description détaillée de l'infographie</button>

    Image captcha

    L’alternative de l’image doit permettre d’identifier la nature de l’image

    <img src="" alt="Code de confirmation à saisir"/>

    Proposer une alternative

    • Captcha sonore; pas idéal, le son peut être dangereux pour certaines typologies
    • Captcha de logique; pas conseiller car problématique pour certaines typologies
    • Envoi du code par email/SMS; Recommander si possible car plus lourd techniquement

    Le captcha de google est conforme !

    Texte en image

    Interdit sauf pour les logos
    ou proposer un mécanisme de remplacement :

    • Déclencher par l'utilisateur via une option accessibilité
    • via un plugin

    Images légendées

    Légende : texte adjacent à une image

    Si un alt est renseigné, il faudrat reporter son contenu dans le aria-label et dans la figcaption

    <figure role="group|figure" aria-label="alt-image Légende de l’image">
        <img src="…" alt="alt-image" />
        <figcaption>
            alt-image Légende de l’image
        </figcaption>
    </figure>
    <figure role="group|figure" aria-label="Légende de l’image">
            <img src="…" alt="" />
            <figcaption>
                Légende de l’image
            </figcaption>
        </figure>

    Si un lien est présent dans le figcaption, reporté unique son intitulé dans le aria-label

    Couleurs

    RGAA : Couleurs

    Information par la couleur

    Cas les plus courants :

    • indication de page active ;
    • indications d’onglets affichés ;
    • carrousel : indication de contenu actif.

    Une information ne doit pas être donnée uniquement par la couleur, ajouter un texte ou une image

    Contrastes

    Ratio minimum
    Inférieur Taille charnière Égal ou supérieur
    Ratio 4.5 Police en 24px Ratio 3
    Ratio 4.5 Police en 18.5px gras Ratio 3

    Ou prévoir un mécanisme de remplacement

    Contrastes des éléments graphiques

    Évaluation pour tous les éléments graphiques porteurs d’information (images, boutons, icônes, etc.) sauf cas particuliers

    • Contraste minimum de 3:1
    • Présence d’un mécanisme de remplacement.

    Exemples de cas particuliers : composant inactif, composants natifs du navigateur, éléments avec une alternative, logo…

    Multimédia

    RGAA : Images

    Média temporel

    Vidéo

    • Contrôles obligatoires
    • Clavier/souris
    • Nom pertinent : mises à jour des noms play/pause
    • Mises à jour des valeurs : timing, son, etc.

    Lecteurs vidéos :

    • Able Player, accessibles
    • MFP Player, accessibles
    • Plyr, accessibles
    • BrightCove, accessibles
    • YouTube, conforme, mais les pubs peuvent être problématiques
    • Dailymotion, non conforme
    • Balise <video> native, problème a priori avec NVDA, a confirmé

    Autres

    Identifiable grâce au contexte adjacent: titre précédent ou texte adjacent

    Alternatives aux médias

    • Transcription textuelle, texte structuré qui reprend l'ensemble du contenu oral et visuel en consultation libre de type Disclosure
    • Sous-titres synchronisés
    • Audiodescription, obligatoire uniquement si la bande son originale dispose des espaces blancs suffisant pour inclure la piste d'audiodescription

    Média non temporel

    Animations intégrées dans Canvas ou svg : Mettre en place une alternative textuelle si nécessaire

    Tableaux

    RGAA : Tableaux

    Faire de la mise en forme

    • Même si leur utilisation pour faire de la mise en forme n'est pas interdite cela n'est pas conseillée
      Si c'est tout de même utilisé pour faire de la mise en en forme, il ne faut pas utiliser des balises ou d’attributs de tableaux de données :
      <th> <thead> <tfoot> <caption> scope headers colgroup axis role="columnheader" role="rowheader"
    • role="presentation" sur la balise table
      Cette propriété supprime la sémantique du tableau, penser à redonner de la structure aux textes (titres, paragraphes, listes ...) dans ces cas.
    • Si la propriété summary="" est présente (HTML4), videz la !
    <table role="presentation">
        <tr>
            <td>
                <p>Retrouvez nos vidéos d’informations !…</p>
            </td>
        </tr>
    </table>

    Tableaux simples

    Sémantique

    • Un titre <caption>
      Si le tableau est précédé d'un titre et que le <caption> est non nécessaire, il faut relié ce titre via un aria-labelledby=""
      <h2 id="exemple">Mon titre</h2>
      <table aria-labelledby="exemple">
          ...
      </table>
    • Déclaration des entêtes <th scope="[col|row]">
      Permets d'indiquer la direction de la cellule d'entête
      Le scope est obligatoire si plusieurs entré
      <table>
          <caption>Parc et fréquentation des autres hébergements collectifs touristiques en 2018</caption>
          <tr>
              <th scope="col">Type d’hébergement professionnel</th>
              <th scope="col">Nombre d’établissements</th>
              [...]
          </tr>
          <tr>
              <td>Résidences de tourisme</td>
              <td>2 426</td>
              [...]
          </tr>
      </table>

    Équivalents ARIA

    • Tableau : role="table"
    • Titre : aria-label="Nom du tableau" ou aria-labelledby="id_titre"
    • Entêtes de colonne : role="columnheader"
    • Entêtes de rangée : role="rowheader"
    • Cellules : role="cell"
    <p id="titre">Parc et fréquentation des autres hébergements collectifs touristiques en 2018</p>
    <div role="table" aria-labelledby="titre">
    
        <div role="row">
            <div role="columnheader">Type d’hébergement professionnel</div>
            <div role="columnheader">Nombre d’établissements</div>
            [...]
        </div>
    
        <div role="row">
            <div role="cell">Résidences de tourisme</div>
            <div role="cell">2 426</div>
            [...]
        </div>
    
    </div>

    Tableaux complexes

    Un tableau est complexe quand il contient plus d'une ligne d'entête (col ou row) ou s'il y a des fusions cellule

    Titre et résumé de l’organisation du tableau

    • Dans le caption ou via le aria-labelledby="", mettre le titre + un résumé de l’organisation du tableau (HTML5)
    • Pour le résumé pour les versions précédentes de HTML, le mettre dans summary=""(HTML4)
    <caption>
        Figure 2 - Répartition des déchets non dangereux non minéraux hors boues de l’industrie
        manufacturière par type en 2016
        <span class="sr-only">
            Les industries agroalimentaires (IAA) et les industries manufacturières (hors IAA)
            sont présentées sur 2 colonnes, avec, pour chacune d’elles la quantité en milliers
            de tonnes le pourcentage. Une troisième colonne présente le total des deux industries,
            en milliers de tonnes et en pourcentage.
        </span>
    </caption>

    Le sommaire, pouvant être utile à d'autres usagers que ceux utilisant un lecteur d'écran, il est préférable de le mettre dans un bloc qui s'affiche via un bouton de type afficher / masquer

    <caption>
        Figure 2 - Répartition des déchets non dangereux non minéraux hors boues de l’industrie
        manufacturière par type en 2016
        <button type="button" aria-expanded="false">Résumé de l’organisation du tableau</button>
        <span class="hide">
            Les industries agroalimentaires (IAA) et les industries manufacturières (hors IAA)
            sont présentées sur 2 colonnes, avec, pour chacune d’elles la quantité en milliers
            de tonnes le pourcentage. Une troisième colonne présente le total des deux industries,
            en milliers de tonnes et en pourcentage.
        </span>
    </caption>

    Version alternative

    Pour les tableaux complexes préférés une alternative car cela inclura tout le monde et non seulement les lecteurs d'écran (et c'est plus simple à développer !)

    • Passage en mode liste par exemple
    • On affiche un bouton pour afficher la version alternative

    Plus besoin de mettre le résumé et header s'il y a une alternative

    Cellules d’en-têtes

    Identifier les cellules d’en-têtes via un attribut id et lier les cellules de données via l’attribut headers.

    Exemple : headers="id_1 id_2".

    <tr>
        <td aria-hidden="true"></td>
        <th id="entete1" colspan="2">Industries agroalimentaires (IAA)</th>
        <th id="entete2" colspan="2">Industries manufacturières (hors IAAA)</th>
        <th id="entete3" colspan="2">Ensemble</th>
    </tr>
    <tr>
        <td aria-hidden="true"></td>
        <th id="entete4">Quantités (en milliers de tonnes)</th>
        <th id="entete5">en %</th>
        <th id="entete6">Quantités (en milliers de tonnes)</th>
        <th id="entete7">en %</th>
        [...]
    </tr>
    <tr>
        <td>Déchets banals</td>
        <td headers="entete1 entete4">1 147</td>
        <td headers="entete1 entete5">31</td>
        <td headers="entete2 entete6">9 795</td>
        <td headers="entete2 entete7">97</td>
        [..]
    </tr>

    Liens

    RGAA : Images

    Liens explicites

    L'intitulé permet de comprendre ou le lien va nous emmener
    ou
    Le contexte le permet (Titre, paragraphe et phrase précédente)

    • «la suite», si le texte est seul, ce n'est pas explicite
    • «la suite», précédé d'un article (titre ou paragraphe), c'est conforme

    Mais on peut améliorer l'intitulé !

    Si un lien n'est pas explicite pour le voyant, ce n'est pas une faute, mais plutôt un problème d'UX
    Le nom visible doit être contenu dans le nom accessible

    Pour expliciter un intitulé :

    • via un texte caché en sr-only : non voyant uniquement
    • title : tous le monde
    • aria-label ou aria-labelledby : pas natif donc pas pour tout le monde

    aria-label

    Doit comporter l'intitulé du lien

    <a href="#url" aria-label="Retour Accueil du site">Retour</a>

    aria-label surcharge l'intitulé, c'est pour ça que l'on doit mettre l'intitulé dedans

    title

    • Le title sera restitué par les lecteurs d'écran et à la souris
    • Par défaut le title est restitué en plus de l'intitulé, mais certain le configure pour etre que seul le title soit restitué

    Doit comporter l'intitulé du lien

    <a href="#url" title="Retour Accueil du site">Retour</a>

    Liens identiques

    Des liens dons l'intitulé et le contexte sont identiques et ont la même destination
    Si ce n'est pas le cas :

    • Ajouter un titre pour préciser la différence entre les liens
    • Changer le contexte

    Liens vides

    Pas de lien vides
    Attention au lien avec des images, aux polices d'icônes où les mise en forme en CSS uniquement (content:"")

    Mettre un alt sur les images liens

    <a href="#lien">
        <img alt="intitule">
    </a>

    Ajouter un aria-label ou aria-labelledby sur le lien si besoin,
    utilisé si possible les propriétés natives

    <a aria-label="intitule">
        <i class="fa-solid fa-house"></i>
    </a>

    Un texte positionné hors de l'écran est la méthode conseillée

    <a href="#lien">
        <span class="sr-only">intitule</span>
        <i class="fa-solid fa-house"></i>
    </a>

    Traduction

    aria-label n'est pas correctement traduit par google translate
    Préféré les méthodes : sr-only ou title

    Scripts

    RGAA : Scripts

    ARIA

    Notes

    Surcharge de propriété, support général bon

    5 règles de base

    1. Privilégier le natif !
      Et tester la restitution.
    2. Ne pas changer la sémantique
      Sémantique de titre conservé, vérifié avec le validateur du W3C si besoin
      <div role="tab">
          <h2>Titre onglet</h2>
      </div>
    3. Composant interactif utilisable au clavier
      • Les composants doivent pouvoir être atteint à la tabulation, voir tabindex
      • Un bouton doit être sélectionnable avec espace et entrée
    4. Ne pas supprimer la sémantique des éléments interactifs ou empêcher leur restitution
      • Attention aria-hidden="true" s'hérite des parents
      • Pour bloquer l'accès à un bouton
        <button type="button" tab-index="-1">Menu</button>
    5. Tout composant interactif doit avoir un nom accessible
      Algorithme de calcul du nom accessible

    Compatibilité

    • Nom, rôle et valeurs
    • Accès à la souris et au clavier
      Voir les Motif de conception (en anglais)
    • Ou une alternative accessible
      Avec un datepicker non conforme, l'ajout d'un input saisissable rend le composant conforme
      (attention à ne pas être piégé dans une boucle de focus)

    Rôle pertinent

    • Lien : changement d'URL
    • Bouton ou implémentation du motif ARIA button : action, événement, fonction JavaScript etc...

    Même pour les single page application ;
    Un composant qui déclenche l'ouverture d'une page ou d'un onglet doit être un lien même si ce sont des actions Javascript

    <a role="link" tabindex="0" onclick="myFunction()"></a>
    <!-- ou -->
    <a href="#" onclick="myFunction()"></a>

    État et changements d'état

    • État sélectionné d'un bouton
      <button aria-pressed="false">Filtrer par nom</button>
      <button aria-pressed="true">Filtrer par nom</button>
    • Composant inactif, on utilisera l'attribut disabled
    • L'attribut aria-expanded="true/false" est défini sur un élément pour indiquer si un contrôle est développé
    • Sur un groupe d'éléments liés, indiquer à l'utilisateur qu'il s'agit de l'élément actuel aria-current
    • Lorsqu'un composant change d'état, que sa fonctionnalité est modifiée, on peut également passer par un changement de nom accessible ou de description (par exemple, la transformation d'un bouton lecture en pause, on vérifiera que l'intitulé a bien été modifié pour retranscrire la fonctionnalité qui sera déclenchée à la prochaine activation du bouton, pas uniquement l'apparence visuelle).
      <button>Lecture</button>
      <button class="hide">Pause</button>
    • Liste exhaustive des États et propriétés ARIA (en anglais)

    Changement de contexte

    • un texte explicatif précédant le changement de contexte
      Ne pas faire de rechargement de page, d'une partie ou de changement de page par défaut, mettre un bouton pour faire l'action
    • un bouton ou un lien explicite

    Message de statut

    Informer les technologies d’assistance des messages d’alerte de confirmation ou de statut, sans déplacer le focus de l'utilisateur.
    Ne pas en abuser, parfois contre-productif

    Si le focus est déplacé sur le message ok/Ko général alors pas besoin de mettre le role="alert" ou si la page se recharge et que le bloc est dans le DOM Dans tous les cas on fait une reprise de focus.

    En cas d'erreur, ont se déplace l'utilisateur sur le premier champ en erreur/ ou message de confirmation + le mieux et de mettre aussi un message dans le titre de la page

    • aria-live="assertive" : le contenu est vocalisé immédiatement
    • aria-live="polite" : le contenu est vocalisé dès que l'utilisateur est disponible
    • aria-atomic="true" restitue tout, à ne pas utiliser dans un tchat par exemple
    • aria-atomic="false" restitue uniquement le dernier ajout

    Messages d'erreurs — Haute priorité

    role="alert"
    Le "alert" est restituée correctement
    <p role="alert">Ceci est une alerte ajoutée dynamiquement</p>
    Méthode alternative :
    aria-live="assertive"
    et
    aria-atomic="true"

    Messages d'informations — Attends que ce soit son tour pour être vocalisé

    Pas très fiable coté restitution, préféré le "alert" si ça beug

    <p role="status">Ceci est un status ajouté dynamiquement</p>
    Méthode alternative :
    aria-live="polite"
    et
    aria-atomic="true"
    <p><span id="myLiveRegion1" aria-live="polite">Mais je sais rester polie</span></p>

    Messages de notifiactions

    role="log"
    Méthode alternative : aria-live="polite"
    et
    aria-atomic="false"

    Messages d’attente

    role="progressbar"

    Seulement pour des tâches qui prennent beaucoup de temps.

    <div role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100">20 %</div>
    ou
    <div role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuetext="Étape 2&nbsp;: Copie des fichiers…" aria-valuemax="100">
        Étape 2&nbsp;: Copie des fichiers…
    </div>

    Repositionner le focus sur un élément pertinent, par exemple la zone mise à jour

    Ressources

    Motif de conception

    Motif de conception (design pattern) : décrit structure, rôles et propriétés et comportement d’un composant JavaScript(widget).
    ARIA authoring practices

    Environnement de test

    Il est nécessaire de réaliser des tests de restitution et d'utilisation avec les lecteurs d'écran de la base de référence.
    Guide sur les lecteurs d'écran.

    Environnement de bureau
    Technologie d’assistance Navigateur
    NVDA (dernière version) Firefox
    JAWS (version précédente) Firefox
    VoiceOver (dernière version) Safari
    Environnement mobile
    Système Technologie d’assistance Navigateur
    iOS VoiceOver (dernière version) Safari
    Android Talkback (dernière version) Chrome

    Pour tester un site web sur un terminal mobile, l’environnement de test devra comporter une des deux combinaisons (iOS ou Android). À noter que dans le cas d’un site web mobile grand public, il est fortement conseillé de tester dans les deux environnements.

    Tableau d'évaluation d'un modif de conception aria (.xlsx 128ko)

    Éléments obligatoires

    RGAA : Éléments obligatoires

    Respect des standard

    Le code doit être valide selon le HTML Checker du w3C

    • <!DOCTYPE > valide
    • lang et/ou xml:lang
    • dirObligatoire si changement de sens de lecture par rapport au reste des pages (rtl ou ltr)
    • Imbrication des balises
    • Ouverture et fermeture des balises & attributs
    • Valeurs d’attribut id sont uniques dans la page
    • Attributs pas doublés sur un même élément.
    • Attributs et éléments obsolètes autorisés (mais à tester sur la base de référence)

    Respect de la sémantique

    Utiliser les balises pour leur rôle prévu par la spécification

    • Pas de <div> pour les paragraphes
    • Pas de balise de titre <hX> pour des légendes d'image
    • Pas de paragraphe vide pour faire des espace
    • <p>a utilisé quand il y a un verbe

    Titre de pages (<title>)

    Obligatoire, pertinent et de préférence unique dans le site

    • Unique
    • Résultat de recherche : doit contenir les mots saisis
    • Ajouter les erreur de formulaire (facultatif, mais conseillé)
    • Ajouter la pagination si il y en une
    • Tag (facultatif, mais conseillé)

    Sans rechargement de page :
    Simuler le rechargement de la page en changeant le <title>, avec les nouvelles informations en synchro avec la page puis déplacer le focus sur le début de la page
    Article pour en savoir davantage :Comment gérer le rechargement de page dans les « Single Page Applications » ?

    Changements de langue

    • Nom propre, lieu, marque, personne : on ne change pas la langue
    • Les mots francisés, exemple «newsletter» «barbecue», «email» : faire un test avec le lecteur d'écran
      • «e-mail»,c'est bon, mais dans «email» sans le tiret deviens «émail»

    En cas de changement de langue, ajouter l'attribut lang sur l’élément ou un parent.

    <p>Des contenus vidéos sur le Web
        (<span lang="en">on</span>
        et <span lang="en">offline</span>).
    </p>

    Changements de sens de lecture

    • dir sur l’élément lui-même ou un parent ;
    • Deux valeurs : ltr ou rtl ;
    • ltr implicite, peut être omise sur l’élément html.
    <span lang="ar" dir="rtl">
        شكرا جزيلا
    </span>

    Structuration de l’information

    RGAA : Structuration de l’information

    Utilisé les régions natives

    <header>
    • Obligatoire pour l’en-tête du document
    • Contenus d’introduction, peut contenir des titres, de la navigation
    • Une balise <header> peux être utiliser dans une <section>
    <main>

    Unique ou une seule balise est visible simultanément

    <section><div>
    • une <div> n'a pas de valeur sémantique
    • une <section> avec titre aria-label ou aria-labelledby : région déclarée dans les plans des lecteurs d'écran, ne pas en abusé car cela alourdit la page et complexifié inutilement le plan
    <nav>

    Réservé aux zones de navigation principale et secondaire

    Les navigations secondaires comprennent :

    • menu de sous-rubrique
    • navigation dans les collections de pages
    • navigation dans les résultats de recherche
    • le Fil d'ariane
    • les liens d’évitement

    Ne pas utiliser <nav> pour les listes de lien !

    Le bouton "burger" doit être inclus dans l'élément <nav>
    La navigation principale peut inclure le bouton burger et être inclus dans la même balise <nav>
    Ou en cas de plusieurs <nav>, le bouton doit être dans une balise <nav> seul

    <aside>
    • Optionnel
    • Contenus indirectement reliés au contenu principal, peuvent être consultés de manière indépendante
    <footer>
    • Obligatoire pour le pied de page du document
    • Contenus de pied de page, d’articles ou de contenus regroupés par <section>

    Titrage du contenu

    • Hiérarchie cohérente, de h1 à h6
      Dans la version 4 du RGAA, la règle est plus souple
      • il peux y avoir des saut entre les titre h2 h4
      • ne pas avoir de h1 peut etre conforme dans certain cas
      • avoir plusieurs h1 c'est conforme aussi
    • Uniquement les titres nécessaires, un texte ne gras n'est pas un titre
    • role="heading" aria-level="[level]" Permet de déclarer un titrage aux technologies d'assistance sans utiliser les balises sémantique, à utiliser en cas de conflit avec les équipe SEO par exemple
      <h1>Accueil…</h1>
          <h2>Actualités…</h2>
              <h2 role="heading" aria-level="3">Où en est-on ?</h2>
              <h2 role="heading" aria-level="3">Ils arrivent bientôt !</h2>

    Listes

    • Liste non ordonnée : ul li
    • Liste ordonnée : ol li
    • Liste de définition : dl dt/dd
      C'est assez lourd pour les lecteurs d'écran, préféré de simples listes sauf pour la réalisation d'un glossaire
      Pour une légende d'un schéma, une liste non ordonnée est plus adaptée
      Un équivalant aux balises sémantiques :
      <div role="list">
      
          <div role="term">Terme à définir…</div>
          <div role="definition"> Définition… </div>
      
          <div role="term">...</div>
          <div role="definition">...</div>
      
      </div>
    • Si pas de possibilité de faire une liste sémantique :
      • role="list" équivalent à un ul
      • role="listitem" équivalent à un li
      <div role="list">
          <div role="listitem">Favoriser l’information…</div>
          <div role="listitem">Permettre aux personnes…</div>
      </div>
    • Les suites de liens doivent être structurées avec des listes.

    Citations

    • Citation en ligne <q>, mal restitué par NVDA préféré la citation de bloc
    • Citation en bloc <blockquote>
      <blockquote>
          <p>Aimer, ce n'est pas se regarder l'un l'autre, c'est regarder ensemble dans la même direction.</p>
          <cite>Antoine De Saint-Exupéry</cite>
      </blockquote>

    Cadres iframe et frame

    • Contenu pertinent, ajouté un title
      <iframe title="Publicité"></iframe>
    • Pas de titre dans le cas de cadres techniques (Google Analytics, etc.) mais cacher avec aria-hidden="true".

    Présentation de l’information

    RGAA : Présentation de l’information

    Utilisation exclusive de CSS

    • Utilisation exclusive de CSS :
      • <link rel="stylesheet"/> ;
      • <style></style> ;
      • ou attributstyle en ligne.
    • Pas d’attribut de mise en forme <table border="0">.
    • Pas de balise de mise en forme <font>.

    Les attributs width et height utilisés sur d’autres éléments que les balises <img>, <object>, <embed>, <canvas> et <svg> sont également interdits.

    Liste complète des attributs et balises interdites.

    Contenus visibles sans CSS

    Le contenu visible reste présent lorsque les feuilles de styles sont désactivées.

    Attention, ne pas faire :

    • Contenu inséré par CSS content (texte, icônes porteuses d’information)
      a[target="_blank"]:after{
          content:"nouvelle fenêtre"
      }
    • Images de fond porteuses d’informations (background-image)
      h1:after{
          background-image:url("logo.png")
      }

    Contenus compréhensibles sans CSS

    Le contenu reste compréhensible lorsque les feuilles de styles sont désactivées.

    • Ordre des éléments logique
    • Ordre des éléments cohérent, l’enchaînement de la lecture est cohérent.
    • Les informations qui se rapportent à un titre doivent être placé après et/ou tout mettre dans un li
    • Le order en CSS n'est pas pris en compte par les lecteurs d'écran, pratique pour réagencer
    • Le bandeau Cookie, doit être placer en début de page avant même le bandeau d'accès rapide
    • Ne rien mettre dans le code après le bouton de validation d'un formulaire

    Couleurs par défaut

    • Toujours déclarer une couleur de texte, de lien et de fond sur le body
      body, body a{color:#000;}
      body{background-color:#fff;}
    • Texte avec une image en arrière-plan : mettre un background-color
      .elt{
          background-image:url(...);
          color:#fff;
          background-color:#000;
      }

    Zoom texte

    Unités des tailles de police :

    • Taille de police relatives : em, rem, %
    • Depuis RGAA 4 : tailles de polices en px autorisées. (non conseillé car les tailles de police en pixels ne permettent pas d’agrandir les textes sur certains navigateurs)
    • Quand un site propose un dispositif d’agrandissement des caractères (A+/A-), c'est cette fonctionnalité qui sera soumise à la conformité, mieux vaut laisser les navigateurs gérés !

    Texte lisible avec agrandissement jusqu'à 200% :

    • Zoom texte : Firefox : « Affichage > Zoom texte seul » : agrandissement à 200% (Ctrl + 6 fois)
    • Ou utilisation des fonctions de zoom du navigateur (zoom graphique)

    Linéarisation des contenus

    Les contenus doivent rester présents, lisibles et utilisables sans utilisation des deux ascenseurs :

    • Consultation verticale : 320px de large minimum
    • Consultation horizontale : 256px de hauteur minimum

    Les tableaux ont le droit d'être affiché avec un scroll

    Adaptation des textes

    Les textes doivent rester lisibles dans les conditions suivantes :

    • interlignage augmenté de 1,5 fois la taille de police ;
    • marge suivante : 2 fois la taille de police
    • espacement des lettres : 0,12 fois la taille de la police
    • espacement des mots : 0,16 fois la taille de la police
    * {
        line-height: 1.5 !important;
        letter-spacing: 0.12em !important;
        word-spacing: 0.16em !important;
    }
    
    p {
        margin-bottom: 2em !important;
    }

    Cas particuliers : sous-titres incrustés, images-texte, texte dans une balise canvas.

    Survol et focus — ancre

    Contenus qui apparaissent à la prise de focus ou au survol d’un élément :

    • Peut être masquer sans déplacer le focus ou le pointeur pointeur via la touche Echap
    • Peut être survolé sans disparaitre
    • Reste visible tant que le composant est actif

    La balise title natif ou modèle de conception ARIA (tooltip, modale) n'est pas concernée par cette règle

    Contrôle des contenus additionnels au clavier — ancre

    Les contenus au survol doivent fonctionner aussi au clavier et autre périphérique de pointage équivalent

    Visibilité de la prise de focus — ancre

    • Pas de dégradation de l'outline natif outline:0 ou outline:none
    • Ou utilisation d’une indication de focus augmentée suffisamment contrastée (ratio mini de 3)

    Les états :focus, :hover des composants doivent également être suffisamment contrastés.

    Attention aux composants interactifs masqués :

    <input type="radio" id="default" class="sr-only" />
    <label for="default">Défaut</label>
    input:focus+label{ outline:1px dotted black }

    Visibilité des liens en environnement de texte — ancre

    A l'intérieur d'un bloc de texte

    • Contraste suffisant (> 3 par rapport au texte environnant) ou ajouter un soulignement
    • Indication supplémentaire a la couleur au survol souris ou prise de focus

    Texte caché — ancre

    Texte caché qui annule aussi la restitution d'écran :

    • display:none
    • visibility:hidden
    • font-size:0

    Uniquement pour la restitution d'écran :
    aria-hidden="true" ou hidden

    Information par la forme, la taille ou la position — ancre

    Pensez au alternative textuelle ou une version alternative :

    • Un petit curseur full CSS
    • Une liste de progression sans texte
    • Une petite fleche pour dire nouvelle fenêtre
    • etc...

    Une information ne doit pas être donnée uniquement par la couleur, ajouter un texte ou une image

    Formulaires

    RGAA : Formulaires

    Étiquette de champ

    Une étiquette pertinente :

    • label visible
    • ou un bouton visible
    • ou, a minima, un attribut title
    • Le placeholder ne remplace pas une étiquette visible.
    • Si title et placeholder alors leur contenu sont identiques
    • Les labels et les champs doivent être accolés, pas de définition claire (à l'appréciation de chacun !)

    Dans le code, le champ doit avoir un nom accessible

    • aria-label
    • aria-labelledby / id
    • <label> avec relation for / id
    • title

    Le placeholder n’est pas un nom accessible robuste

    Information complémentaire

    • Ajouté le complément directe dans l'étiquette de champ
      L'utilisation d'une double <label for=""> est déconseiller
      <label for="name">
          <strong>Prénom</strong><br>
          40 caractere max
      </label>
      <input id="name"/>
    • ou une combinaison de label et de aria-describedby
      <label for="name">Prénom</label>
      <input id="name" aria-describedby="info"/>
      <p id="info">40 caractere max</p>
    • ou utilisé un aria-labelledby multiple
      <p id="label">Prénom</p>
      <input type="text" aria-labelledby="label info"/>
      <p id="info">40 caractere max</p>

    Nom visible et nom accessible

    Le nom visible doit être contenu dans le nom accessible
    Attention à l'algorithme de calcul du nom accessible

    Regroupement de champs

    Réunir les éléments communs avec :

    • <fieldset> et titrer avec <legend>
      <fieldset>
          <legend>Adresse de facturation</legend>
          [champs ...]
      </fieldset>
    • ou une div avec le role="group" et titrer avec aria-label ou aria-labelledby
      <div role="group" aria-labelledby="toto">
          <p id="toto">Adresse de livraison</p>
          [champs ...]
      </div>

    La légende peut être masqué mais doit être restitué par les lecteurs d'écran

    Exemple courant de regroupement à faire :

    • Ensemble de Radio
    • Ensemble de Chexbox
    • Période d'une date (debut, fin)
    • Ajouter un personne, se répétant, (nom, prénom, age)

    Liste de choix

    Regrouper les items de même nature d’une liste de choix <select> si nécessaire

    <select>
        <optgroup label="Véhicules">
            <option>Voiture</option>
            <option>Motos</option>
            …
        </optgroup>
        <optgroup label="Immobilier">
            <option>Maison</option>
            <option>Appartements</option>
            …
        </optgroup>
    </select>

    Intitulés de bouton

    • L'intitulé (nom accessible) est pertinent ;
      • «Valider» : ne permet pas de comprendre ce qui va se passer
      • «Calculer la simulation» : pertinent
    • Si le bouton possède un nom visible alors il est aussi contenu dans le nom accessible
    <input type="submit" value="Envoyer le message" />
    
    <input type="image" src="loupe.png" alt="Rechercher sur le site">
    
    <input type="submit" value="OK" title="Envoyer le message" />
    
    <input type="submit" aria-label="Effacer mes données"/>
    
    <input type="submit" aria-labelledby="desc-btn" />
    <span id="desc-btn">Envoyer le message</span>

    Champ obligatoire et facultatif

    • Tout est obligatoire : Mettre en début de formulaire que tous les champs sont obligatoires
    • Mixte : Ajouter une astérisque dans les champs obligatoire + mettre une légende en haut du formulaire
    • Majorité de facultatif : Possibililité de mettre les champs optionnels directement après le label
    • Ou au moyen d'un texte relié avec aria-describedby
      <label for="name">Prénom</label>
      <input id="name" aria-describedby="required"/>
      <p id="required">Champs obligatoire</p>
    • Il faut une indication visible, un attribut required ne suffit pas !

    Aides et contrôles de saisie

    • Format attendu : fournir le format de saisie
    • Contrôle de saisie : fournir un exemple de saisie
    • Directement dans l'étiquette du champ concerné
    • Ou via l’attribut aria-describedby="id_dun_texte", voir Information complémentaire
    • L'indication doit être visible

    Message d'erreur

    Le message doit être visible est restitué
    Les textes liés par les propriétés aria-labelledby ou aria-describedby font partie des propriétés de l’élément, ils sont donc toujours disponibles, y compris lorsqu’ils sont cachés par CSS avec display:none ou visibility:hidden

    Champ obligatoire : format attendu à fournir (a faire de facon global si possible)
    Message générique dans le titre de la page : « erreur sur le formulaire » est très suffisant

    • Dans le message d'erreur on peut donner :
      • un exemple réel 01/02/23 au lieu du JJ/MM/AAAA, pour une date c'est clairement mieux, mais pour une adresse email c'est moins intéressant
      • de l'aide à la complétion, pas obligatoire mais mieux
    • Les exemples de format ne doivent pas être que dans les placeholders car ce n'est pas accessible

    Personnaliser les messages d’erreurs natif

    L'API Constraint validation permet de personnaliser les messages d’erreurs générés par les type d’input particuliers.

    <form>
        <label class="label" for="emailform">Votre email:</label>
        <p><input type="email" name="email" id="emailform"></p>
        <input type="submit" value="valider">
    </form>
    var email = document.getElementById("emailform");
    email.addEventListener('invalid', function() {
        if (this.value.trim() !== '') {
            this.setCustomValidity("Saisie invalide. Exemple valide\n: toto@foobar.com");
        }
    }, false);

    Modification, mises à jour ou récupération des données

    Si le formulaire

    • modifie ou supprime des données ;
    • ou transmet des données sensibles, réponses à un examen ;
    • a des conséquences financières, juridiques.

    L'utilisateurs doit pouvoir

    • vérifier, modifier ou annuler les saisies avant envoie du formulaire ;
    • ou il existe un mécanisme de confirmation explicite via une case à cocher ou une étape supplémentaire.

    Pour les formulaires de signature électronique, type mandat SEPA, la modification peut être désactivé comme le but de ces formulaires est de valider les données saisies précédemment

    Champs avec saisi automatique

    Pour les champs qui collectent des informations personnelles sur l’utilisateur, la nature du champ (finalité) est déterminable à partir du code (attributs/propriétés).

    Utilisation de l’attribut autocomplete

    La liste des valeurs disponibles est fournie par la spécification WCAG 2.1 :

    • name - Nom complet ;
    • honorific-prefix - Abréviation, civilité ou titre ;
    • given-name - Prénom ;
    • additional-name - Prénoms additionnels ;
    • family-name - Nom de famille ;
    • honorific-suffix - Suffixe honorifique ;
    • nickname - Surnom, diminutif ;
    • organization-title - Fonction, intitulé de poste ;
    • username - Nom d’utilisateur ;
    • new-password - Nouveau mot de passe (par exemple, lors de la création d’un compte ou d’un changement de mot de passe) ;
    • current-password - Mot de passe actuel pour le compte identifié par le champ username (par exemple, lors d’une connexion) ;
    • organization - Nom de l’organisation correspondant à la personne, à l’adresse ou à l’information de contact dans les autres champs associés avec ce champ ;
    • street-address - Adresse postale (multiligne, nouvelles lignes conservées) - attention champ textarea attendu ;
    • address-line1 - Adresse postale (une ligne par champ, ligne 1) ;
    • address-line2 - Adresse postale (une ligne par champ, ligne 2) ;
    • address-line3 - Adresse postale (une ligne par champ, ligne 3) ;
    • address-level4 - Le niveau administratif le plus détaillé, pour les adresses pourvues de quatre niveaux administratifs ;
    • address-level3 - Le troisième niveau administratif, pour les adresses pourvues d’au moins trois niveaux administratifs ;
    • address-level2 - Le deuxième niveau administratif, pour les adresses pourvues d’au moins deux niveaux administratifs ;
    • address-level1 - Le plus large niveau administratif d’une adresse, c’est-à-dire la province dans laquelle se trouve la localité ;
    • country - Code pays ;
    • country-name - Nom de pays ;
    • postal-code - Code postal, code CEDEX (si le CEDEX est présent, ajouter “CEDEX”, et ce qui le suit doit être ajouté dans le champ address-level2) ;
    • cc-name - Nom complet figurant sur le moyen de paiement ;
    • cc-given-name - Prénom figurant sur le moyen de paiement ;
    • cc-additional-name - Prénoms additionnels figurant sur le moyen de paiement cc-family-name - Nom de famille figurant sur le moyen de paiement ;
    • cc-number - Code identifiant le moyen de paiement (e.g., un numéro de carte bancaire) ;
    • cc-exp - Date d’expiration du moyen de paiement ;
    • cc-exp-month - Le mois de la date d’expiration du moyen de paiement ;
    • cc-exp-year - L’année de la date d’expiration du moyen de paiement ;
    • cc-csc - Code de sécurité du moyen de paiement (also known as the card security code (CSC), card validation code (CVC), card verification value (CVV), signature panel code (SPC), credit card ID (CCID), etc.) ;
    • cc-type - Type de moyen de paiement (e.g. Visa) ;
    • transaction-currency - La devise qui a la préférence de l’utilisateur lors d’une transaction ;
    • transaction-amount - Le montant qui a la préférence de l’utilisateur lors d’une transaction (e.g., en réponse à une enchère ou à un prix soldé) ;
    • language - Langue préférée ;
    • bday - Date d’anniversaire ;
    • bday-day - Le jour de la date d’anniversaire ;
    • bday-month - Le mois de la date d’anniversaire ;
    • bday-year - L’année de la date d’anniversaire ;
    • sex - Identité sexuelle ;
    • url - Page d’accueil ou une autre page Web correspondant à l’organisation, la personne, l’adresse ou à l’information de contact dans les autres champs associés avec ce champ ;
    • photo - Photographie, icône ou une autre image correspondant à l’organisation, la personne, l’adresse ou à l’information de contact dans les autres champs associés avec ce champ ;
    • tel - Numéro de téléphone complet, y compris le code pays ;
    • tel-country-code - Code pays du numéro de téléphone ;
    • tel-national - Numéro de téléphone sans la partie code pays, avec un préfixe interne au pays, s’il y a lieu ;
    • tel-area-code - Indicatif régional du numéro de téléphone, avec un préfixe interne au pays, s’il y a lieu ;
    • tel-local - Numéro de téléphone sans la partie code pays ni l’indicatif régional ;
    • tel-local-prefix - La première partie du composant du numéro de téléphone qui suit l’indicatif régional, lorsque ce composant est scindé en deux parties ;
    • tel-local-suffix - La seconde partie du composant du numéro de téléphone qui suit l’indicatif régional, lorsque ce composant est scindé en deux parties ;
    • tel-extension - Numéro de téléphone d’un poste interne ;
    • email - Adresse électronique ;
    • impp - URL correspondant d’un protocole de messagerie instantanée (par exemple, "aim:goim?screenname=example" ou "xmpp:fred@example.net").

    Navigation

    RGAA : Navigation

    Lien d’accès rapide

    • Accès rapide au contenu principal (obligatoire), d'autres lien possible sans en abuser
    • Visible à la prise de focus
    • Doit se trouver en premier dans le code HTML de la page
    • tabindex="-1" sur l'élément cible pour se retrouver sur la zone et non sur un élément à l'intérieur
      <a href="#main">contenu</a>
      <main id="main" tabindex="-1"> .... </main>

    Positionnement hors écran

    .sr-only {
        border: 0 !important;
        clip: rect(1px, 1px, 1px, 1px) !important;
        -webkit-clip-path: inset(50%) !important;
        clip-path: inset(50%) !important;
        height: 1px !important;
        margin: -1px !important;
        overflow: hidden !important;
        padding: 0 !important;
        position: absolute !important;
        width: 1px !important;
        white-space: nowrap !important;
    }

    Improved par #FFOODD

    Landmarks ARIA

    • Uniques dans la page :
      • role="banner" pour l’en-tête du document
      • role="main"
      • role="contentinfo" pour le pied de page
      • role="search" pour un formulaire de recherche, a positionner sur le conteneur du formulaire, pas sur la balise form
      • role="complementary" pour l'<aside>
    • role="navigation" : plusieurs occurrences autorisées pour les navigations principales et secondaires

    Systèmes de navigation

    Il faut en avoir au moins deux parmi :

    • Menu de navigation
    • Plan du site
    • Moteur de recherche
    • Même place dans chaque ensemble de pages.
    • Présentation cohérente dans chaque ensemble de pages.

    La page d'accueil peut avoir un mise en page différente, navigation comprise

    Plan du site

    • Même place dans chaque ensemble de pages.
    • Même méthode dans chaque ensemble de pages.
    • Représentatif de l’architecture générale du site, pas besoin d'avoir toutes les pages référencer
    • Tous les liens sont fonctionnels avec des intitulés pertinents

    Moteur de recherche

    • Même place dans chaque ensemble de pages.
    • Même méthode dans chaque ensemble de pages.
    • Doit indexer tous les contenus

    Fil d'Ariane

    • Pas d'obligation de le mettre dans le <main>, peut-être en fin de contenu ou dans le pied de page !
    • Tous les liens sont fonctionnels avec des intitulés pertinents

    Ordre de tabulation, piège au clavier

    • Ordre de tabulation cohérent avec le code ; titre avant paragraphe, ordre des conteneurs ( vérifier avec le site sans styles)
    • Pas de piège au clavier (focus figé, focus sur un élément invisible, bug JS, boucle infinie)
      Attention au datepicker, pensez à mettre un bouton calendrier pour ouvrir et surtout fermer le calendrier pour éviter toute boucle
    • Ne jamais utiliser des tabindex supérieurs à 0, laissez le navigateur faire
      Il peut avoir plusieurs tabindex="0" et tabindex="-1" dans une page

      tabindex="0"

      Permets de capturer le focus et être atteint via la navigation au clavier
      Inclut l'élément dans le parcours séquentiel de tabulation pour un élément qui ne prend pas le focus, une div par exemple

      tabindex="-1"
      • L'élément peut capturer le focus mais ne peut pas être atteint via la navigation au clavier
      • Exclu du parcours séquentiel un élément qui prend le focus (lien, button…)
      • Permets à l'élément ne prenant pas nativement le focus de le recevoir (méthode javascript focus)
      • Attention l'élément restera accessible par les techniques d'assistance (différent d'aria hidden="true")

    Accès au contenu additionnel affiché

    • L'élément doit être atteint au clavier
    • La zone doit rester visible tant que le focus se trouve dans l'élément

    Penser à mettre un bouton fermer pour pouvoir revenir à l'endroit initial (un bouton qui ouvre un pop-in après le footer dans le code)

    Raccourcis clavier

    • Désactiver ou permettre de configurer les raccourcis
    • Ou le raccourci n'est effectif que lorsque le focus est dans le composant sur lequel il s'applique

    Consultation

    RGAA : Consultation

    Limite de temps de session

    • L’utilisateur doit pouvoir supprimer ou augmenter la limite de temps ;
    • La limite de temps est de vingt heures au moins ;
    • Cas particulier lorsque la limite de temps est essentielle.

    Il faut penser à ceux qui on besoin plus de temps que les autres pour faire les mêmes manipulations, pour un utilisateur de contacteur au souffle ou autre par exemple

    Afficher un message dans une modale par exemple pour prolonger ou supprimer la limite de session

    Rafraichissement automatique

    • L'utilisateur peut arrêter et relancer le rafraîchissement ;
    • L'utilisateur est alerté de l’imminence d’un rafraichissement et peut augmenter le délai de 10 fois au moins.

    Que le rafraîchissement soit total soit partiel, proposer un bouton pour désactiver/activer le live upload par exemple

    Nouvelles fenêtres

    • Pas de nouvelles fenêtres sans action de l’utilisateur
    • Une seule fenêtre s'ouvre à la fois

    Documents en téléchargement

    • Document accessible ;
    • Ou alternative accessible : HTML, .doc, .odt structurés.

    Pensez à fournir une alternative, notamment pour les PDF qui sont très difficile a rendre accessible

    Ressources : Liste des critères Documents bureautiques en téléchargement (Le Grand-Duché de Luxembourg, docx, 66 kilo-octets). Attention basé sur le RGAA 3

    Clignotement et contenus en mouvement

    L'utilisateur doit pouvoir :

    • Arrêter et relancer, sur un slider prévoir un bouton pause s'il se lance automatiquement
    • Masquer et réafficher
    • Afficher le contenu sans le mouvement
    • Le mouvement dure 5 secondes ou moins
    • Contrôle individuel

    Évité de lancer une vidéo, un son ou un slider automatiquement

    Effet de flash

    • Fréquence limite =< 3 flash par seconde
    • ou surface cumulée =< 21824 pixels

    Outil PEAT (Photosensitive Epilepsy Analysis Tool)

    Mauvais exemple : London 2012 Olympics Seizure

    Son déclenché automatiquement

    • Les sons et vidéo doivent être contrôlable
    • On évite de les lancer automatiquement bien sur !
    • De préférence, le contrôle doit être le premier élément de la page.

    Indépendance de l’orientation

    • Le contenu doite être consultable portrait et paysage, ne pas bloquer
    • Sauf si l'orientation est essentielle

    Gestes complexes

    Les fonctionnalités utilisables par des gestes multipoints (zoom sur une carte) ou basés sur un tracé (swipe) :

    • peuvent être réalisées avec un geste à point unique et/ou sans trajectoire,
    • sauf si le geste est essentiel(ex. le dessin d’une signature).

    Sur une slider au swipe, ajouter une navigation avec des boutons !

    Annulation du pointeur

    • Aucun événement ne doit être déclenché sur l’action descendante
      (down : mousedown sur desktop / touchstart sur mobile)
    • ou prévoir un mécanisme qui permet d’interrompre l'exécution de l'action avant la fin ;
    • ou un mécanisme permet d’annuler l'action.

    Activation par le mouvement

    Les fonctions qui sont déclenchées en déplaçant l’appareil (en secouant ou en basculant) ou lorsque l’utilisateur effectue un mouvement capté par les dispositifs de l’appareil (eg. une caméra) peuvent être :

    • actionnées par des composants classiques (un bouton) ;
    • désactivées pour éviter un déclenchement accidentel ;
    • sauf si le mouvement est essentiel pour la fonction.
Retour en haut