37 min de lecture · 8 119 mots

Accessibilité Web (WCAG 2.2) – Guide des standards

Accessibilité Web (WCAG 2.2) – Guide des standards
Article · 2025.12.19

Guide de référence complet pour l’accessibilité web : standards WCAG 2.2, ARIA, HTML sémantique, navigation clavier, lecteurs d’écran et outils de test.

Table des matières

  1. Introduction WCAG 2.2
  2. HTML sémantique
  3. ARIA (Accessible Rich Internet Applications)
  4. Navigation clavier
  5. Formulaires accessibles
  6. Images et médias
  7. Couleurs et contrastes
  8. Typographie et lisibilité
  9. Lecteurs d’écran
  10. Navigation et structure
  11. Animations et interactions
  12. Outils de test et validation

Introduction WCAG 2.2

Principes POUR (WCAG)

1. Perceptible : L’information doit être présentée de façon à être perçue par tous 2. Opérable : Les composants de l’interface doivent être utilisables 3. Compréhensible : L’information et l’interface doivent être compréhensibles 4. Robuste : Le contenu doit être compatible avec les technologies d’assistance

Niveaux de conformité

Niveau Description Usage
A Niveau minimal Exigences de base
AA Niveau recommandé Standard professionnel (requis légalement dans beaucoup de pays)
AAA Niveau optimal Excellence en accessibilité

Nouveautés WCAG 2.2 (2023)

Nouveaux critères :

  • 2.4.11 Focus Not Obscured (Minimum) – AA
  • 2.4.12 Focus Not Obscured (Enhanced) – AAA
  • 2.4.13 Focus Appearance – AAA
  • 2.5.7 Dragging Movements – AA
  • 2.5.8 Target Size (Minimum) – AA
  • 3.2.6 Consistent Help – A
  • 3.3.7 Redundant Entry – A
  • 3.3.8 Accessible Authentication (Minimum) – AA
  • 3.3.9 Accessible Authentication (Enhanced) – AAA

HTML sémantique

Structure de page sémantique

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Titre descriptif de la page</title>
</head>
<body>
    <!-- Skip link (lien d'évitement) -->
    <a href="#main-content" class="skip-link">Aller au contenu principal</a>

    <!-- En-tête du site -->
    <header role="banner">
        <div class="logo">
            <img src="logo.svg" alt="Logo de l'entreprise">
        </div>

        <!-- Navigation principale -->
        <nav role="navigation" aria-label="Navigation principale">
            <ul>
                <li><a href="/">Accueil</a></li>
                <li><a href="/services">Services</a></li>
                <li><a href="/contact">Contact</a></li>
            </ul>
        </nav>
    </header>

    <!-- Contenu principal -->
    <main id="main-content" role="main">
        <!-- Article ou section -->
        <article>
            <h1>Titre principal de la page</h1>

            <section aria-labelledby="section1-title">
                <h2 id="section1-title">Première section</h2>
                <p>Contenu de la section...</p>
            </section>

            <section aria-labelledby="section2-title">
                <h2 id="section2-title">Deuxième section</h2>
                <p>Contenu de la section...</p>
            </section>
        </article>

        <!-- Contenu complémentaire -->
        <aside role="complementary" aria-label="Informations complémentaires">
            <h2>Articles connexes</h2>
            <ul>
                <li><a href="/article1">Article 1</a></li>
                <li><a href="/article2">Article 2</a></li>
            </ul>
        </aside>
    </main>

    <!-- Pied de page -->
    <footer role="contentinfo">
        <p>&copy; 2025 Entreprise. Tous droits réservés.</p>
        <nav aria-label="Navigation secondaire">
            <ul>
                <li><a href="/mentions-legales">Mentions légales</a></li>
                <li><a href="/confidentialite">Confidentialité</a></li>
            </ul>
        </nav>
    </footer>
</body>
</html>

Balises sémantiques HTML5

<!-- Navigation -->
<nav aria-label="Navigation principale">
    <ul>
        <li><a href="/">Accueil</a></li>
    </ul>
</nav>

<!-- En-tête -->
<header>
    <h1>Titre du site</h1>
</header>

<!-- Contenu principal -->
<main>
    <!-- Contenu unique de la page -->
</main>

<!-- Article autonome -->
<article>
    <h2>Titre de l'article</h2>
    <p>Contenu de l'article...</p>
</article>

<!-- Section thématique -->
<section aria-labelledby="section-title">
    <h2 id="section-title">Titre de section</h2>
    <p>Contenu...</p>
</section>

<!-- Contenu complémentaire -->
<aside>
    <h2>Informations connexes</h2>
</aside>

<!-- Pied de page -->
<footer>
    <p>Informations de contact</p>
</footer>

<!-- Figure avec légende -->
<figure>
    <img src="chart.png" alt="Graphique des ventes 2024">
    <figcaption>Évolution des ventes sur l'année 2024</figcaption>
</figure>

<!-- Définitions -->
<dl>
    <dt>HTML</dt>
    <dd>HyperText Markup Language</dd>
    <dt>CSS</dt>
    <dd>Cascading Style Sheets</dd>
</dl>

<!-- Marquage sémantique inline -->
<p>
    Ce texte contient un <strong>mot important</strong> et un
    <em>mot accentué</em>. Le code s'écrit avec <code>&lt;code&gt;</code>.
</p>

<!-- Abréviations -->
<abbr title="World Wide Web Consortium">W3C</abbr>

<!-- Citations -->
<blockquote cite="https://source.com">
    <p>Citation longue...</p>
    <footer>- <cite>Auteur</cite></footer>
</blockquote>

<!-- Heure/Date -->
<time datetime="2025-01-15">15 janvier 2025</time>

Landmarks ARIA

<!-- Banner (en-tête principal) -->
<header role="banner">
    <!-- Ou simplement <header> si unique dans la page -->
</header>

<!-- Navigation -->
<nav role="navigation" aria-label="Navigation principale">
    <!-- Ou simplement <nav> avec aria-label -->
</nav>

<!-- Main (contenu principal) -->
<main role="main">
    <!-- Ou simplement <main> -->
</main>

<!-- Complementary (contenu complémentaire) -->
<aside role="complementary">
    <!-- Ou simplement <aside> -->
</aside>

<!-- Contentinfo (pied de page) -->
<footer role="contentinfo">
    <!-- Ou simplement <footer> si à la racine -->
</footer>

<!-- Search (zone de recherche) -->
<div role="search">
    <form>
        <input type="search" aria-label="Rechercher">
        <button type="submit">Rechercher</button>
    </form>
</div>

<!-- Region (section importante) -->
<section role="region" aria-labelledby="region-title">
    <h2 id="region-title">Titre de la région</h2>
</section>

Checklist HTML sémantique

  • [ ] Balises HTML5 sémantiques utilisées (header, nav, main, article, aside, footer)
  • [ ] Un seul <main> par page
  • [ ] Un seul <h1> par page
  • [ ] Hiérarchie des titres respectée (h1 → h2 → h3…)
  • [ ] Landmarks ARIA appropriés
  • [ ] Attribut lang sur <html>
  • [ ] Pas de balises dépréciées (font, center, etc.)
  • [ ] HTML valide (W3C validator)

ARIA (Accessible Rich Internet Applications)

Règles d’or ARIA

  1. N’utilisez pas ARIA si HTML sémantique suffit
  2. Ne changez pas la sémantique native
  3. Tous les contrôles interactifs doivent être utilisables au clavier
  4. Ne pas utiliser role= »presentation » ou aria-hidden sur éléments focusables
  5. Tous les éléments interactifs doivent avoir un nom accessible

Rôles ARIA essentiels

<!-- Button -->
<div role="button" tabindex="0" aria-pressed="false">
    Bouton personnalisé
</div>
<!-- Préférer : <button>Bouton</button> -->

<!-- Link -->
<div role="link" tabindex="0">Lien personnalisé</div>
<!-- Préférer : <a href="...">Lien</a> -->

<!-- Checkbox -->
<div role="checkbox" aria-checked="false" tabindex="0">
    Case à cocher
</div>
<!-- Préférer : <input type="checkbox"> -->

<!-- Radio -->
<div role="radio" aria-checked="false" tabindex="0">
    Bouton radio
</div>
<!-- Préférer : <input type="radio"> -->

<!-- Tablist / Tab / Tabpanel -->
<div role="tablist" aria-label="Onglets de contenu">
    <button role="tab" aria-selected="true" aria-controls="panel1" id="tab1">
        Onglet 1
    </button>
    <button role="tab" aria-selected="false" aria-controls="panel2" id="tab2">
        Onglet 2
    </button>
</div>
<div role="tabpanel" id="panel1" aria-labelledby="tab1">
    Contenu onglet 1
</div>
<div role="tabpanel" id="panel2" aria-labelledby="tab2" hidden>
    Contenu onglet 2
</div>

<!-- Dialog (modale) -->
<div role="dialog" aria-labelledby="dialog-title" aria-modal="true">
    <h2 id="dialog-title">Titre de la modale</h2>
    <p>Contenu de la modale</p>
    <button>Fermer</button>
</div>

<!-- Alert -->
<div role="alert" aria-live="assertive">
    Message d'alerte important
</div>

<!-- Status -->
<div role="status" aria-live="polite" aria-atomic="true">
    Chargement en cours...
</div>

<!-- Menu / Menuitem -->
<div role="menu" aria-label="Options">
    <div role="menuitem">Option 1</div>
    <div role="menuitem">Option 2</div>
    <div role="menuitem">Option 3</div>
</div>

<!-- Progressbar -->
<div role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100">
    75%
</div>

<!-- Slider -->
<div role="slider" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100" tabindex="0">
    Slider
</div>

Propriétés ARIA

<!-- aria-label : nom accessible -->
<button aria-label="Fermer la fenêtre">
    <span aria-hidden="true">×</span>
</button>

<!-- aria-labelledby : référence à un label -->
<h2 id="section-title">Titre de section</h2>
<div aria-labelledby="section-title">
    Contenu de la section
</div>

<!-- aria-describedby : description supplémentaire -->
<input
    type="text"
    id="username"
    aria-describedby="username-help"
>
<span id="username-help">
    Entre 3 et 20 caractères
</span>

<!-- aria-hidden : cacher aux lecteurs d'écran -->
<span aria-hidden="true">★</span>
<span class="sr-only">Note : 4 étoiles sur 5</span>

<!-- aria-live : région dynamique -->
<div aria-live="polite" aria-atomic="true">
    <!-- Contenu qui se met à jour -->
</div>
<!-- polite = attendre la fin de la lecture -->
<!-- assertive = interrompre immédiatement -->

<!-- aria-current : élément actuel -->
<nav>
    <a href="/" aria-current="page">Accueil</a>
    <a href="/about">À propos</a>
    <a href="/contact">Contact</a>
</nav>

<!-- aria-expanded : état déplié/replié -->
<button aria-expanded="false" aria-controls="menu">
    Menu
</button>
<ul id="menu" hidden>
    <li>Item 1</li>
    <li>Item 2</li>
</ul>

<!-- aria-pressed : bouton toggle -->
<button aria-pressed="false">
    Mode sombre
</button>

<!-- aria-checked : état coché -->
<div role="checkbox" aria-checked="true">
    Accepter les conditions
</div>

<!-- aria-selected : élément sélectionné -->
<div role="tab" aria-selected="true">
    Onglet actif
</div>

<!-- aria-disabled : désactivé -->
<button aria-disabled="true">
    Bouton désactivé
</button>
<!-- Préférer : <button disabled> -->

<!-- aria-required : champ requis -->
<input
    type="text"
    aria-required="true"
>
<!-- Préférer : <input required> -->

<!-- aria-invalid : validation -->
<input
    type="email"
    aria-invalid="true"
    aria-describedby="email-error"
>
<span id="email-error" role="alert">
    Format d'email invalide
</span>

<!-- aria-haspopup : indique un popup -->
<button aria-haspopup="menu" aria-expanded="false">
    Options
</button>

Live Regions (contenu dynamique)

<!-- Notification non-critique -->
<div role="status" aria-live="polite" aria-atomic="true">
    <p>Message enregistré avec succès</p>
</div>

<!-- Alerte importante -->
<div role="alert" aria-live="assertive" aria-atomic="true">
    <p>Erreur : veuillez remplir tous les champs obligatoires</p>
</div>

<!-- Timer / Compteur -->
<div aria-live="off" aria-atomic="true" id="timer">
    00:30
</div>

<!-- Loading state -->
<div role="status" aria-live="polite" aria-busy="true">
    <span>Chargement en cours...</span>
</div>

<!-- Résultats de recherche -->
<div role="region" aria-live="polite" aria-atomic="true">
    <p>42 résultats trouvés</p>
</div>

Checklist ARIA

  • [ ] ARIA utilisé uniquement si HTML sémantique insuffisant
  • [ ] Tous les contrôles ARIA utilisables au clavier
  • [ ] États ARIA mis à jour dynamiquement (aria-expanded, aria-pressed, etc.)
  • [ ] Live regions pour contenu dynamique
  • [ ] aria-label ou aria-labelledby sur éléments interactifs
  • [ ] aria-hidden sur éléments purement décoratifs
  • [ ] Pas de role= »presentation » sur éléments focusables
  • [ ] Validation ARIA (axe DevTools, WAVE)

Ordre de tabulation

<!-- Ordre naturel du DOM (recommandé) -->
<button>Bouton 1</button>
<button>Bouton 2</button>
<button>Bouton 3</button>

<!-- tabindex="0" : inclure dans ordre naturel -->
<div role="button" tabindex="0">
    Bouton personnalisé
</div>

<!-- tabindex="-1" : focusable par JS, pas par Tab -->
<div tabindex="-1" id="error-message">
    Message d'erreur
</div>

<!-- ÉVITER : tabindex positif (ordre imprévisible) -->
<button tabindex="1">Ne pas faire</button>
<button tabindex="2">Mauvaise pratique</button>

Raccourcis clavier

Touche Action standard
Tab Élément suivant
Shift + Tab Élément précédent
Enter Activer lien/bouton
Espace Activer bouton, toggle checkbox
Flèches Navigation dans menus, tabs, sliders
Échap Fermer dialog/menu
Home Début de liste/contenu
End Fin de liste/contenu
Page Up/Down Scroll par page
<!-- Skip link -->
<style>
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: #000;
  color: #fff;
  padding: 8px;
  z-index: 100;
}

.skip-link:focus {
  top: 0;
}
</style>

<a href="#main-content" class="skip-link">
  Aller au contenu principal
</a>

<!-- Menu déroulant accessible clavier -->
<nav>
  <button
    aria-expanded="false"
    aria-controls="submenu"
    aria-haspopup="true"
  >
    Menu
  </button>
  <ul id="submenu" hidden>
    <li><a href="/page1">Page 1</a></li>
    <li><a href="/page2">Page 2</a></li>
  </ul>
</nav>

<script>
const menuButton = document.querySelector('[aria-controls="submenu"]');
const submenu = document.getElementById('submenu');

menuButton.addEventListener('click', toggleMenu);
menuButton.addEventListener('keydown', (e) => {
  if (e.key === 'Enter' || e.key === ' ') {
    e.preventDefault();
    toggleMenu();
  }
  if (e.key === 'Escape') {
    closeMenu();
  }
});

function toggleMenu() {
  const isExpanded = menuButton.getAttribute('aria-expanded') === 'true';
  menuButton.setAttribute('aria-expanded', !isExpanded);
  submenu.hidden = isExpanded;

  if (!isExpanded) {
    submenu.querySelector('a')?.focus();
  }
}

function closeMenu() {
  menuButton.setAttribute('aria-expanded', 'false');
  submenu.hidden = true;
  menuButton.focus();
}
</script>

Focus visible

/* Reset du outline natif (MAUVAIS) */
*:focus {
  outline: none; /* NE PAS FAIRE */
}

/* Style de focus personnalisé (BON) */
*:focus {
  outline: 2px solid #0066cc;
  outline-offset: 2px;
}

/* Focus visible uniquement clavier (moderne) */
*:focus-visible {
  outline: 2px solid #0066cc;
  outline-offset: 2px;
}

/* Désactiver focus visible pour souris */
*:focus:not(:focus-visible) {
  outline: none;
}

/* Skip link focus */
.skip-link:focus {
  position: absolute;
  top: 0;
  left: 0;
  background: #000;
  color: #fff;
  padding: 8px 16px;
  text-decoration: none;
  z-index: 9999;
}

/* Focus dans composants personnalisés */
[role="button"]:focus,
[role="link"]:focus {
  outline: 2px solid #0066cc;
  outline-offset: 2px;
}

Piège clavier (focus trap dans modales)

// Piéger le focus dans une modale
class FocusTrap {
  constructor(element) {
    this.element = element;
    this.focusableElements = element.querySelectorAll(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    );
    this.firstFocusable = this.focusableElements[0];
    this.lastFocusable = this.focusableElements[this.focusableElements.length - 1];
  }

  activate() {
    this.element.addEventListener('keydown', this.handleKeyDown.bind(this));
    this.firstFocusable?.focus();
  }

  deactivate() {
    this.element.removeEventListener('keydown', this.handleKeyDown.bind(this));
  }

  handleKeyDown(e) {
    if (e.key === 'Tab') {
      if (e.shiftKey) {
        // Shift + Tab
        if (document.activeElement === this.firstFocusable) {
          e.preventDefault();
          this.lastFocusable?.focus();
        }
      } else {
        // Tab
        if (document.activeElement === this.lastFocusable) {
          e.preventDefault();
          this.firstFocusable?.focus();
        }
      }
    }

    if (e.key === 'Escape') {
      this.close();
    }
  }

  close() {
    // Logique de fermeture
    this.deactivate();
  }
}

// Utilisation
const modal = document.querySelector('[role="dialog"]');
const focusTrap = new FocusTrap(modal);
focusTrap.activate();

Checklist Navigation clavier

  • [ ] Tous les éléments interactifs accessibles au clavier
  • [ ] Ordre de tabulation logique
  • [ ] Focus visible sur tous les éléments focusables
  • [ ] Skip link présent
  • [ ] Pas de piège clavier (sauf modales)
  • [ ] Focus retourne à l’élément déclencheur après fermeture modale
  • [ ] Raccourcis clavier documentés si personnalisés
  • [ ] Pas d’utilisation de tabindex positif
  • [ ] Flèches fonctionnent dans composants appropriés (menus, sliders)
  • [ ] Échap ferme les overlays/modales

Formulaires accessibles

Structure de formulaire accessible

<form action="/submit" method="post">
  <!-- Label associé à input -->
  <div>
    <label for="name">Nom complet <abbr title="requis" aria-label="requis">*</abbr></label>
    <input
      type="text"
      id="name"
      name="name"
      required
      aria-required="true"
      autocomplete="name"
    >
  </div>

  <!-- Input avec description -->
  <div>
    <label for="email">Email</label>
    <input
      type="email"
      id="email"
      name="email"
      required
      aria-required="true"
      aria-describedby="email-help"
      autocomplete="email"
    >
    <span id="email-help" class="help-text">
      Nous ne partagerons jamais votre email
    </span>
  </div>

  <!-- Input avec erreur -->
  <div>
    <label for="phone">Téléphone</label>
    <input
      type="tel"
      id="phone"
      name="phone"
      aria-invalid="true"
      aria-describedby="phone-error"
      autocomplete="tel"
    >
    <span id="phone-error" role="alert" class="error">
      Format invalide. Utilisez : 06 12 34 56 78
    </span>
  </div>

  <!-- Groupe de radio buttons -->
  <fieldset>
    <legend>Choisissez votre abonnement</legend>
    <div>
      <input type="radio" id="basic" name="plan" value="basic">
      <label for="basic">Basic (9€/mois)</label>
    </div>
    <div>
      <input type="radio" id="pro" name="plan" value="pro">
      <label for="pro">Pro (19€/mois)</label>
    </div>
    <div>
      <input type="radio" id="enterprise" name="plan" value="enterprise">
      <label for="enterprise">Enterprise (49€/mois)</label>
    </div>
  </fieldset>

  <!-- Groupe de checkboxes -->
  <fieldset>
    <legend>Préférences de notification</legend>
    <div>
      <input type="checkbox" id="email-notif" name="notifications" value="email">
      <label for="email-notif">Email</label>
    </div>
    <div>
      <input type="checkbox" id="sms-notif" name="notifications" value="sms">
      <label for="sms-notif">SMS</label>
    </div>
  </fieldset>

  <!-- Select -->
  <div>
    <label for="country">Pays</label>
    <select id="country" name="country" required autocomplete="country">
      <option value="">-- Sélectionnez un pays --</option>
      <option value="BE">Belgique</option>
      <option value="CH">Suisse</option>
    </select>
  </div>

  <!-- Textarea -->
  <div>
    <label for="message">Message</label>
    <textarea
      id="message"
      name="message"
      rows="5"
      aria-describedby="message-help"
      maxlength="500"
    ></textarea>
    <span id="message-help">
      Maximum 500 caractères
    </span>
  </div>

  <!-- Boutons -->
  <div>
    <button type="submit">Envoyer</button>
    <button type="reset">Réinitialiser</button>
    <a href="/" role="button">Annuler</a>
  </div>
</form>

Validation accessible

<!-- Message d'erreur global -->
<div role="alert" aria-live="assertive" id="form-errors">
  <h2>Erreurs dans le formulaire</h2>
  <ul>
    <li><a href="#name">Le nom est requis</a></li>
    <li><a href="#email">L'email est invalide</a></li>
  </ul>
</div>

<!-- Champ avec erreur -->
<div class="form-field error">
  <label for="email">Email</label>
  <input
    type="email"
    id="email"
    name="email"
    aria-invalid="true"
    aria-describedby="email-error"
    class="error"
  >
  <span id="email-error" role="alert">
    Veuillez entrer un email valide
  </span>
</div>

<!-- Champ valide -->
<div class="form-field success">
  <label for="username">Nom d'utilisateur</label>
  <input
    type="text"
    id="username"
    name="username"
    aria-invalid="false"
    aria-describedby="username-success"
  >
  <span id="username-success" role="status">
    ✓ Nom d'utilisateur disponible
  </span>
</div>

Autocomplete

<!-- Attributs autocomplete appropriés -->
<input type="text" name="name" autocomplete="name">
<input type="email" name="email" autocomplete="email">
<input type="tel" name="phone" autocomplete="tel">
<input type="text" name="organization" autocomplete="organization">
<input type="text" name="street" autocomplete="street-address">
<input type="text" name="city" autocomplete="address-level2">
<input type="text" name="postal" autocomplete="postal-code">
<input type="text" name="country" autocomplete="country">
<input type="text" name="cc-number" autocomplete="cc-number">
<input type="text" name="cc-exp" autocomplete="cc-exp">

Checklist Formulaires

  • [ ] Tous les inputs ont un label associé (for/id)
  • [ ] Labels visibles (pas uniquement placeholder)
  • [ ] Champs requis indiqués visuellement et programmatiquement
  • [ ] Erreurs de validation claires et spécifiques
  • [ ] Erreurs annoncées aux lecteurs d’écran (role= »alert »)
  • [ ] aria-invalid sur champs en erreur
  • [ ] aria-describedby pour aide et erreurs
  • [ ] Fieldset/legend pour groupes de champs
  • [ ] Autocomplete approprié
  • [ ] Focus sur premier champ en erreur après soumission
  • [ ] Bouton submit clairement identifié

Images et médias

Images accessibles

<!-- Image informative -->
<img
  src="chart.png"
  alt="Graphique montrant une augmentation de 25% des ventes en 2024"
  width="800"
  height="600"
>

<!-- Image décorative -->
<img src="decoration.png" alt="" role="presentation">

<!-- Image avec légende -->
<figure>
  <img
    src="product.jpg"
    alt="Smartphone noir avec écran OLED de 6,5 pouces"
  >
  <figcaption>
    Nouveau modèle X - Disponible en 3 couleurs
  </figcaption>
</figure>

<!-- Image complexe (avec longdesc alternative) -->
<img
  src="complex-chart.png"
  alt="Graphique des tendances de marché 2024"
  aria-describedby="chart-description"
>
<div id="chart-description" class="sr-only">
  <p>Description détaillée : Le graphique montre...</p>
</div>

<!-- SVG accessible -->
<svg role="img" aria-labelledby="svg-title">
  <title id="svg-title">Icône de validation</title>
  <path d="..."/>
</svg>

<!-- SVG décoratif -->
<svg aria-hidden="true" focusable="false">
  <path d="..."/>
</svg>

<!-- Image map -->
<img
  src="map.png"
  alt="Plan du campus"
  usemap="#campus-map"
>
<map name="campus-map">
  <area
    shape="rect"
    coords="0,0,100,100"
    href="/building-a"
    alt="Bâtiment A - Administration"
  >
  <area
    shape="rect"
    coords="100,0,200,100"
    href="/building-b"
    alt="Bâtiment B - Bibliothèque"
  >
</map>

<!-- Lazy loading -->
<img
  src="image.jpg"
  alt="Description de l'image"
  loading="lazy"
  width="800"
  height="600"
>

Vidéos accessibles

<!-- Vidéo avec sous-titres et transcription -->
<figure>
  <video controls width="640" height="360">
    <source src="video.mp4" type="video/mp4">
    <source src="video.webm" type="video/webm">

    <!-- Sous-titres (captions) -->
    <track
      kind="captions"
      src="captions-fr.vtt"
      srclang="fr"
      label="Français"
      default
    >
    <track
      kind="captions"
      src="captions-en.vtt"
      srclang="en"
      label="English"
    >

    <!-- Descriptions audio -->
    <track
      kind="descriptions"
      src="descriptions-fr.vtt"
      srclang="fr"
      label="Descriptions français"
    >

    <!-- Chapitres -->
    <track
      kind="chapters"
      src="chapters.vtt"
      srclang="fr"
      label="Chapitres"
    >

    <!-- Fallback -->
    <p>
      Votre navigateur ne supporte pas la vidéo HTML5.
      <a href="video.mp4">Télécharger la vidéo</a>
    </p>
  </video>

  <figcaption>
    <details>
      <summary>Transcription de la vidéo</summary>
      <p>Transcription textuelle complète de la vidéo...</p>
    </details>
  </figcaption>
</figure>

<!-- Format WebVTT (captions-fr.vtt) -->
<!--
WEBVTT

00:00:00.000 --> 00:00:03.000
Bienvenue dans cette vidéo tutoriel.

00:00:03.000 --> 00:00:07.000
Aujourd'hui, nous allons apprendre l'accessibilité web.
-->

Audio accessible

<figure>
  <audio controls>
    <source src="podcast.mp3" type="audio/mpeg">
    <source src="podcast.ogg" type="audio/ogg">

    <!-- Transcription obligatoire pour audio -->
    <p>
      Votre navigateur ne supporte pas l'élément audio.
      <a href="podcast.mp3">Télécharger le podcast</a>
    </p>
  </audio>

  <figcaption>
    <details>
      <summary>Transcription de l'audio</summary>
      <p>Transcription complète du contenu audio...</p>
    </details>
  </figcaption>
</figure>

Checklist Médias

  • [ ] Toutes les images ont un attribut alt approprié
  • [ ] Images décoratives avec alt= » » ou role= »presentation »
  • [ ] Vidéos ont des sous-titres (captions)
  • [ ] Vidéos ont une transcription textuelle
  • [ ] Audio a une transcription textuelle
  • [ ] Contrôles média accessibles au clavier
  • [ ] Pas de lecture automatique (autoplay)
  • [ ] SVG ont title ou aria-label si informatifs
  • [ ] Width et height définis sur images (CLS)

Couleurs et contrastes

Ratios de contraste WCAG 2.2

Élément Niveau AA Niveau AAA
Texte normal (< 18pt) 4.5:1 7:1
Texte large (≥ 18pt ou ≥ 14pt gras) 3:1 4.5:1
Composants UI et graphiques 3:1 –
Texte de logo Pas de minimum –

Exemples de contrastes

/* BON : Contraste 7:1 (AAA) */
.text-high-contrast {
  color: #000000; /* Noir */
  background-color: #ffffff; /* Blanc */
}

/* BON : Contraste 4.52:1 (AA pour texte normal) */
.text-good-contrast {
  color: #595959; /* Gris foncé */
  background-color: #ffffff; /* Blanc */
}

/* INSUFFISANT : Contraste 2.9:1 */
.text-poor-contrast {
  color: #999999; /* Gris */
  background-color: #ffffff; /* Blanc */
  /* Ne passe pas AA */
}

/* BON : Texte large avec contraste 3:1 */
.large-text {
  font-size: 18pt;
  font-weight: bold;
  color: #767676;
  background-color: #ffffff;
}

/* Boutons et composants UI : 3:1 minimum */
.button {
  background-color: #0066cc;
  border: 2px solid #004080; /* Contraste 3.2:1 avec background */
}

/* Focus indicator : 3:1 minimum */
*:focus-visible {
  outline: 2px solid #0066cc; /* Contraste avec arrière-plan */
  outline-offset: 2px;
}

Ne pas utiliser uniquement la couleur

<!-- MAUVAIS : information uniquement par couleur -->
<p style="color: red;">Champ requis</p>

<!-- BON : combinaison couleur + texte/icône -->
<p>
  <span style="color: red;">*</span>
  <span>Champ requis</span>
</p>

<!-- BON : états de formulaire -->
<div class="form-field error">
  <label for="email">Email</label>
  <input type="email" id="email" aria-invalid="true">
  <span class="error-icon" aria-hidden="true">❌</span>
  <span class="error-message">Email invalide</span>
</div>

<!-- BON : graphique avec motifs -->
<svg role="img" aria-label="Graphique des ventes">
  <!-- Barres avec différentes couleurs ET motifs -->
  <rect fill="blue" />
  <rect fill="red" pattern="url(#stripes)" />
</svg>

<!-- BON : liens distinguables sans couleur -->
<style>
a {
  color: #0066cc;
  text-decoration: underline; /* Toujours souligné */
}
</style>

Mode sombre accessible

/* Variables CSS pour thème */
:root {
  --text-primary: #000000;
  --background-primary: #ffffff;
  --link-color: #0066cc;
}

@media (prefers-color-scheme: dark) {
  :root {
    --text-primary: #ffffff;
    --background-primary: #1a1a1a;
    --link-color: #66b3ff; /* Plus clair pour bon contraste */
  }
}

/* Utilisation */
body {
  color: var(--text-primary);
  background-color: var(--background-primary);
}

a {
  color: var(--link-color);
}

/* Toggle manuel */
[data-theme="dark"] {
  --text-primary: #ffffff;
  --background-primary: #1a1a1a;
  --link-color: #66b3ff;
}

Checklist Couleurs

  • [ ] Contraste texte normal ≥ 4.5:1 (AA)
  • [ ] Contraste texte large ≥ 3:1 (AA)
  • [ ] Contraste composants UI ≥ 3:1
  • [ ] Information pas uniquement par couleur
  • [ ] Liens distinguables (underline ou bold)
  • [ ] Focus visible avec bon contraste
  • [ ] Mode sombre accessible si présent
  • [ ] Palette testée (outils contraste)

Typographie et lisibilité

Taille de texte

/* Texte de base : minimum 16px */
body {
  font-size: 16px;
  line-height: 1.5; /* 150% minimum */
}

/* Texte peut être zoomé jusqu'à 200% sans perte de fonctionnalité */
/* Utiliser unités relatives (rem, em) */
h1 {
  font-size: 2rem; /* 32px si base = 16px */
}

p {
  font-size: 1rem; /* 16px */
  line-height: 1.5; /* 24px */
}

/* Texte large pour accessibilité */
.large-text {
  font-size: 1.125rem; /* 18px */
  line-height: 1.6;
}

/* ÉVITER : taille fixe en pixels pour texte */
/* Empêche le zoom texte du navigateur */

Espacement

/* Espacement pour lisibilité (WCAG 2.2 - 1.4.12) */
* {
  /* Line height : minimum 1.5x font-size */
  line-height: 1.5;

  /* Espacement paragraphes : minimum 2x font-size */
  margin-bottom: 2em;

  /* Letter spacing : minimum 0.12x font-size */
  letter-spacing: 0.12em;

  /* Word spacing : minimum 0.16x font-size */
  word-spacing: 0.16em;
}

/* Largeur de ligne optimale */
p {
  max-width: 70ch; /* 70 caractères maximum par ligne */
}

Polices lisibles

/* Polices sans-serif pour écrans */
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
}

/* Éviter polices trop stylisées pour contenu principal */
.decorative-heading {
  font-family: 'Fancy Font', cursive;
  /* OK pour titres courts, pas pour paragraphes */
}

/* Dyslexie : polices spécialisées */
.dyslexia-friendly {
  font-family: 'OpenDyslexic', 'Comic Sans MS', sans-serif;
}

Justification et alignement

/* Éviter justification complète (difficile à lire) */
.text-block {
  text-align: left; /* BON */
  /* text-align: justify; */ /* ÉVITER pour accessibilité */
}

/* Césure contrôlée */
p {
  hyphens: auto;
  overflow-wrap: break-word;
}

Checklist Typographie

  • [ ] Taille de texte base ≥ 16px
  • [ ] Line-height ≥ 1.5
  • [ ] Texte zoomable jusqu’à 200%
  • [ ] Unités relatives (rem, em, %)
  • [ ] Largeur de ligne ≤ 80 caractères
  • [ ] Espacement paragraphes suffisant
  • [ ] Pas de justification pour longs textes
  • [ ] Police lisible
  • [ ] Pas de texte en image (sauf logo)

Lecteurs d’écran

Screen reader only (SR-only)

/* Classe pour texte visible uniquement par lecteurs d'écran */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* Visible au focus (skip links) */
.sr-only-focusable:focus {
  position: static;
  width: auto;
  height: auto;
  overflow: visible;
  clip: auto;
  white-space: normal;
}

Exemples d’utilisation

<!-- Contexte supplémentaire pour SR -->
<button>
  <span aria-hidden="true">×</span>
  <span class="sr-only">Fermer la fenêtre</span>
</button>

<!-- Information visuelle explicitée -->
<a href="/cart">
  Panier
  <span class="badge">3</span>
  <span class="sr-only">3 articles dans le panier</span>
</a>

<!-- États visuels -->
<div class="status-icon success" aria-hidden="true">✓</div>
<span class="sr-only">Opération réussie</span>

<!-- Navigation par landmarks -->
<nav aria-label="Navigation principale">
  <span class="sr-only">Début de la navigation principale</span>
  <ul>
    <li><a href="/">Accueil</a></li>
  </ul>
  <span class="sr-only">Fin de la navigation principale</span>
</nav>

Texte alternatif de qualité

<!-- BON : descriptif et concis -->
<img src="dog.jpg" alt="Golden retriever jouant avec une balle rouge dans un parc">

<!-- MAUVAIS : redondant -->
<img src="photo.jpg" alt="Photo d'un golden retriever jouant avec une balle rouge dans un parc">

<!-- MAUVAIS : trop vague -->
<img src="image.jpg" alt="Image">

<!-- BON : contexte du lien -->
<a href="/article">
  <img src="thumb.jpg" alt="Lire l'article : 10 astuces SEO">
</a>

<!-- MAUVAIS : "cliquez ici" -->
<a href="/article">
  <img src="thumb.jpg" alt="Cliquez ici">
</a>

Ordre de lecture

<!-- L'ordre DOM = ordre de lecture -->
<!-- BON : ordre logique -->
<article>
  <h2>Titre de l'article</h2>
  <p class="date">15 janvier 2025</p>
  <p>Contenu de l'article...</p>
  <a href="/lire-plus">Lire la suite</a>
</article>

<!-- MAUVAIS : ordre visuel ≠ ordre DOM -->
<article>
  <p style="order: 3">Contenu...</p>
  <h2 style="order: 1">Titre</h2>
  <p class="date" style="order: 2">Date</p>
  <!-- Lecteur d'écran lit dans ordre DOM, pas ordre visuel -->
</article>

Checklist Lecteurs d’écran

  • [ ] Contenu important pas dans aria-hidden
  • [ ] Textes alternatifs descriptifs
  • [ ] Ordre DOM logique
  • [ ] .sr-only pour contexte supplémentaire
  • [ ] aria-label sur éléments sans label visible
  • [ ] Landmarks ARIA appropriés
  • [ ] Live regions pour contenu dynamique
  • [ ] Test avec lecteur d’écran (NVDA, JAWS, VoiceOver)

Fil d’Ariane (Breadcrumb)

<nav aria-label="Fil d'Ariane">
  <ol>
    <li>
      <a href="/">Accueil</a>
    </li>
    <li>
      <a href="/categorie">Catégorie</a>
    </li>
    <li>
      <a href="/sous-categorie">Sous-catégorie</a>
    </li>
    <li aria-current="page">
      Page actuelle
    </li>
  </ol>
</nav>

Pagination

<nav aria-label="Pagination" role="navigation">
  <ul>
    <li>
      <a href="/page/1" aria-label="Aller à la page 1">
        <span aria-hidden="true">‹‹</span>
        <span class="sr-only">Première page</span>
      </a>
    </li>
    <li>
      <a href="/page/4" aria-label="Page précédente">
        <span aria-hidden="true">‹</span>
        <span class="sr-only">Précédent</span>
      </a>
    </li>
    <li>
      <a href="/page/3">3</a>
    </li>
    <li>
      <a href="/page/4">4</a>
    </li>
    <li aria-current="page">
      <span class="current-page">
        5
        <span class="sr-only">(page actuelle)</span>
      </span>
    </li>
    <li>
      <a href="/page/6">6</a>
    </li>
    <li>
      <a href="/page/7">7</a>
    </li>
    <li>
      <a href="/page/6" aria-label="Page suivante">
        <span aria-hidden="true">›</span>
        <span class="sr-only">Suivant</span>
      </a>
    </li>
    <li>
      <a href="/page/10" aria-label="Aller à la dernière page (page 10)">
        <span aria-hidden="true">››</span>
        <span class="sr-only">Dernière page</span>
      </a>
    </li>
  </ul>
</nav>

Table des matières

<nav aria-labelledby="toc-heading">
  <h2 id="toc-heading">Table des matières</h2>
  <ol>
    <li>
      <a href="#section1">Introduction</a>
    </li>
    <li>
      <a href="#section2">Méthodes</a>
      <ol>
        <li><a href="#section2-1">Méthode A</a></li>
        <li><a href="#section2-2">Méthode B</a></li>
      </ol>
    </li>
    <li>
      <a href="#section3">Conclusion</a>
    </li>
  </ol>
</nav>

Checklist Navigation

  • [ ] Navigation principale identifiée (nav + aria-label)
  • [ ] Skip links présents
  • [ ] Fil d’Ariane si applicable
  • [ ] Pagination accessible
  • [ ] Lien actuel identifié (aria-current= »page »)
  • [ ] Landmarks ARIA (banner, main, navigation, etc.)
  • [ ] Table des matières pour longs articles
  • [ ] Tous les liens ont texte descriptif

Animations et interactions

Respecter prefers-reduced-motion

/* Animations par défaut */
.element {
  transition: transform 0.3s ease;
}

.element:hover {
  transform: scale(1.1);
}

/* Désactiver pour utilisateurs sensibles */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Alternative : animations subtiles */
@media (prefers-reduced-motion: reduce) {
  .element {
    transition: opacity 0.3s ease; /* OK */
    /* transition: transform 0.3s ease; */ /* Éviter */
  }
}

Timeout et limites de temps

<!-- Avertir l'utilisateur avant timeout -->
<div role="alert" aria-live="assertive" id="session-warning" hidden>
  <p>
    Votre session expirera dans <span id="countdown">60</span> secondes.
    <button onclick="extendSession()">Prolonger la session</button>
  </p>
</div>

<script>
let timeoutDuration = 1800000; // 30 minutes
let warningTime = 60000; // 1 minute avant

function startSessionTimer() {
  setTimeout(() => {
    showWarning();
  }, timeoutDuration - warningTime);
}

function showWarning() {
  document.getElementById('session-warning').hidden = false;
  startCountdown(60);
}

function extendSession() {
  document.getElementById('session-warning').hidden = true;
  startSessionTimer();
}
</script>

Carrousel accessible

<section aria-roledescription="carrousel" aria-label="Produits vedettes">
  <!-- Contrôles -->
  <div class="carousel-controls">
    <button
      aria-label="Diapositive précédente"
      onclick="previousSlide()"
    >
      ‹
    </button>

    <button
      aria-label="Pause automatique"
      aria-pressed="false"
      id="pause-button"
      onclick="toggleAutoplay()"
    >
      Pause
    </button>

    <button
      aria-label="Diapositive suivante"
      onclick="nextSlide()"
    >
      ›
    </button>
  </div>

  <!-- Slides -->
  <div class="carousel-slides">
    <div
      class="slide"
      role="group"
      aria-roledescription="diapositive"
      aria-label="1 sur 4"
      aria-hidden="false"
    >
      <img src="product1.jpg" alt="Description produit 1">
      <p>Produit 1</p>
    </div>

    <div
      class="slide"
      role="group"
      aria-roledescription="diapositive"
      aria-label="2 sur 4"
      aria-hidden="true"
      hidden
    >
      <img src="product2.jpg" alt="Description produit 2">
      <p>Produit 2</p>
    </div>

    <!-- Autres slides... -->
  </div>

  <!-- Indicateurs -->
  <div class="carousel-indicators" role="tablist">
    <button
      role="tab"
      aria-label="Diapositive 1"
      aria-selected="true"
      onclick="goToSlide(0)"
    ></button>
    <button
      role="tab"
      aria-label="Diapositive 2"
      aria-selected="false"
      onclick="goToSlide(1)"
    ></button>
  </div>
</section>

Checklist Animations

  • [ ] prefers-reduced-motion respecté
  • [ ] Pas d’animations automatiques critiques
  • [ ] Contrôle pause/lecture pour animations
  • [ ] Timeouts avec avertissement et extension possible
  • [ ] Pas de clignotement > 3 fois/seconde
  • [ ] Carrousels avec contrôles accessibles
  • [ ] Auto-scroll désactivable

Outils de test et validation

Outils automatiques

Outil Type URL
WAVE Extension navigateur https://wave.webaim.org/
axe DevTools Extension navigateur https://www.deque.com/axe/
Lighthouse Chrome DevTools Intégré Chrome
Pa11y CLI https://pa11y.org/
Accessibility Insights Extension + Desktop https://accessibilityinsights.io/
ARC Toolkit Extension Chrome https://www.tpgi.com/arc-platform/arc-toolkit/

Outils de contraste

Outil Usage
WebAIM Contrast Checker https://webaim.org/resources/contrastchecker/
Colour Contrast Analyser Application desktop
Stark Plugin Figma/Sketch

Lecteurs d’écran

Lecteur Plateforme Navigateur
NVDA Windows Firefox, Chrome
JAWS Windows Chrome, Edge
VoiceOver macOS/iOS Safari
Narrator Windows Edge
TalkBack Android Chrome

Checklist de tests

Tests automatiques

  • [ ] WAVE : 0 erreur
  • [ ] axe DevTools : 0 erreur
  • [ ] Lighthouse Accessibility : score > 90
  • [ ] HTML valide (W3C validator)
  • [ ] Contraste vérifié (tous textes/composants)

Tests manuels

  • [ ] Navigation clavier complète
  • [ ] Tous les éléments interactifs accessibles
  • [ ] Ordre de tabulation logique
  • [ ] Focus visible sur tous éléments
  • [ ] Skip links fonctionnels
  • [ ] Formulaires testés avec validation
  • [ ] Modales/overlays avec focus trap
  • [ ] Zoom texte 200% fonctionnel

Tests lecteurs d’écran

  • [ ] Test NVDA (Windows)
  • [ ] Test VoiceOver (macOS/iOS)
  • [ ] Landmarks correctement annoncés
  • [ ] Titres correctement hiérarchisés
  • [ ] Images alt text appropriés
  • [ ] Formulaires labels annoncés
  • [ ] Live regions fonctionnelles
  • [ ] États ARIA annoncés (expanded, pressed, etc.)

Tests utilisateurs

  • [ ] Tests avec utilisateurs réels en situation de handicap
  • [ ] Tests sur différents devices
  • [ ] Tests avec assistances technologies variées

Checklist WCAG 2.2 complète

Niveau A (minimum)

Perceptible

  • [ ] 1.1.1 Contenu non textuel (alt text)
  • [ ] 1.2.1 Audio et vidéo en différé (alternative)
  • [ ] 1.2.2 Sous-titres (pré-enregistré)
  • [ ] 1.2.3 Audio-description (pré-enregistré)
  • [ ] 1.3.1 Info et relations (sémantique HTML)
  • [ ] 1.3.2 Ordre séquentiel logique
  • [ ] 1.3.3 Caractéristiques sensorielles
  • [ ] 1.4.1 Utilisation de la couleur
  • [ ] 1.4.2 Contrôle du son

Opérable

  • [ ] 2.1.1 Clavier
  • [ ] 2.1.2 Pas de piège clavier
  • [ ] 2.1.4 Raccourcis clavier
  • [ ] 2.2.1 Réglage du délai
  • [ ] 2.2.2 Mettre en pause, arrêter, masquer
  • [ ] 2.3.1 Pas de clignotement
  • [ ] 2.4.1 Contourner des blocs (skip links)
  • [ ] 2.4.2 Titre de page
  • [ ] 2.4.3 Parcours du focus
  • [ ] 2.4.4 Fonction du lien (contexte)
  • [ ] 2.5.1 Gestes pour le pointeur
  • [ ] 2.5.2 Annulation de l’action du pointeur
  • [ ] 2.5.3 Étiquette dans le nom
  • [ ] 2.5.4 Activation par le mouvement

Compréhensible

  • [ ] 3.1.1 Langue de la page
  • [ ] 3.2.1 Au focus
  • [ ] 3.2.2 À la saisie
  • [ ] 3.2.6 Aide cohérente (nouveau 2.2)
  • [ ] 3.3.1 Identification des erreurs
  • [ ] 3.3.2 Étiquettes ou instructions
  • [ ] 3.3.7 Saisie redondante (nouveau 2.2)

Robuste

  • [ ] 4.1.1 Analyse syntaxique (déprécié en 2.2)
  • [ ] 4.1.2 Nom, rôle et valeur
  • [ ] 4.1.3 Messages de statut

Niveau AA (recommandé)

Perceptible

  • [ ] 1.2.4 Sous-titres (en direct)
  • [ ] 1.2.5 Audio-description (pré-enregistré)
  • [ ] 1.3.4 Orientation
  • [ ] 1.3.5 Identification de la finalité
  • [ ] 1.4.3 Contraste minimum (4.5:1)
  • [ ] 1.4.4 Redimensionnement du texte
  • [ ] 1.4.5 Texte sous forme d’image
  • [ ] 1.4.10 Reflow
  • [ ] 1.4.11 Contraste non textuel
  • [ ] 1.4.12 Espacement du texte
  • [ ] 1.4.13 Contenu au survol ou au focus

Opérable

  • [ ] 2.4.5 Accès multiples
  • [ ] 2.4.6 En-têtes et étiquettes
  • [ ] 2.4.7 Visibilité du focus
  • [ ] 2.4.11 Focus non obscurci (minimum) (nouveau 2.2)
  • [ ] 2.5.7 Mouvements de glissement (nouveau 2.2)
  • [ ] 2.5.8 Taille de la cible (minimum) (nouveau 2.2)

Compréhensible

  • [ ] 3.1.2 Langue d’un passage
  • [ ] 3.2.3 Navigation cohérente
  • [ ] 3.2.4 Identification cohérente
  • [ ] 3.3.3 Suggestion d’erreur
  • [ ] 3.3.4 Prévention des erreurs (juridique, financier)
  • [ ] 3.3.8 Authentification accessible (minimum) (nouveau 2.2)

Niveau AAA (optimal)

Perceptible

  • [ ] 1.2.6 Langue des signes (pré-enregistré)
  • [ ] 1.2.7 Audio-description étendue
  • [ ] 1.2.8 Média de remplacement
  • [ ] 1.2.9 Audio seulement (en direct)
  • [ ] 1.4.6 Contraste amélioré (7:1)
  • [ ] 1.4.7 Fond sonore faible ou absent
  • [ ] 1.4.8 Présentation visuelle
  • [ ] 1.4.9 Texte sous forme d’image (sans exception)

Opérable

  • [ ] 2.1.3 Clavier (sans exception)
  • [ ] 2.2.3 Pas de délai
  • [ ] 2.2.4 Interruptions
  • [ ] 2.2.5 Re-authentification
  • [ ] 2.2.6 Délais d’expiration
  • [ ] 2.3.2 Trois flashs
  • [ ] 2.3.3 Animations dues aux interactions
  • [ ] 2.4.8 Localisation
  • [ ] 2.4.9 Fonction du lien (seul)
  • [ ] 2.4.10 En-têtes de section
  • [ ] 2.4.12 Focus non obscurci (amélioré) (nouveau 2.2)
  • [ ] 2.4.13 Apparence du focus (nouveau 2.2)
  • [ ] 2.5.5 Taille de la cible (amélioré)
  • [ ] 2.5.6 Mécanismes de saisie

Compréhensible

  • [ ] 3.1.3 Mots inhabituels
  • [ ] 3.1.4 Abréviations
  • [ ] 3.1.5 Niveau de lecture
  • [ ] 3.1.6 Prononciation
  • [ ] 3.2.5 Changement à la demande
  • [ ] 3.3.5 Aide
  • [ ] 3.3.6 Prévention des erreurs (toutes)
  • [ ] 3.3.9 Authentification accessible (amélioré) (nouveau 2.2)

Ressources

Documentation officielle

Guides et tutoriels

Législation

  • Union européenne : Directive (UE) 2016/2102 et norme EN 301 549
  • Europe : European Accessibility Act
  • USA : ADA (Americans with Disabilities Act), Section 508

Version : WCAG 2.2 (octobre 2023) Dernière mise à jour : Décembre 2024

Ce guide couvre les standards WCAG 2.2 et les meilleures pratiques d’accessibilité web pour créer des expériences inclusives pour tous les utilisateurs.

Une remarque, un retour ?

Cet article est vivant - corrections, contre-arguments et retours de production sont les bienvenus. Trois canaux, choisis celui qui te convient.

Laisser un commentaire