Accessibilitéconformité

L'accessibilité n'est pas une option — c'est un droit fondamental. Elle garantit que tout le monde, quelles que soient ses capacités, peut utiliser votre site web ou service.

Aux États-Unis, l'accessibilité est régie par l'ADA. Dans l'UE et en France, elle est encadrée par le RGAA, sous la surveillance d'organismes comme le Défenseur des Droits et l'Arcom. Depuis 2022, l'État français peut infliger des sanctions financières — jusqu'à 25 000 € par an de non-conformité.

Les institutions publiques, les grandes entreprises privées et l'e-commerce sont les premières cibles — mais tout le monde devrait s'en soucier. Pas seulement pour éviter les amendes, mais pour offrir une expérience meilleure et plus inclusive.

Partie 1 – Design Accessible

L'accessibilité commence dès la phase de design. Si votre fichier Figma exclut des utilisateurs, votre code le fera aussi. Voici à quoi penser lors de la conception :

  • Contraste des couleurs : Utilisez des outils comme UseContrast ou le plugin Figma Stark pour vérifier les contrastes conformes WCAG.
  • Hiérarchie du texte : Définissez des styles de titres logiques et cohérents (équivalents H1–H6) et évitez de sauter des niveaux.
  • Taille des cibles interactives : Assurez-vous que tous les boutons et éléments cliquables font au moins 44×44px.
  • Styles de focus : Rendez le focus clavier visible. Utilisez une couleur ou un style de bordure cohérent dans vos composants.
  • Navigation : Pensez linéaire. L'ordre de lecture doit avoir du sens même sans les visuels — testez avec des plugins comme SimulAT.
  • Logique des modales & overlays : Planifiez où le focus atterrit, comment il est piégé (trapped), et où il retourne quand la modale ferme.
  • Ne comptez pas que sur la couleur : Utilisez des labels textuels ou des icônes avec des formes distinctes.
  • Dark mode & contraste élevé : Concevez avec un contraste suffisant dans tous les thèmes.

Partie 2 – Développement Accessible

Les développeurs sont les gardiens de l'accessibilité réelle. Voici les fondations techniques et les patterns à suivre :

  • HTML Sémantique : Pas de soupe de divs. Utilisez des balises structurelles.
    <main>
      <article>
        <h2>Article de Blog</h2>
        <p>Le contenu va ici.</p>
      </article>
    </main>
  • Menu de navigation :
    <nav aria-label="Navigation principale">
      <ul>
        <li><a href="/a-propos">À propos</a></li>
        <li><a href="/services">Services</a></li>
      </ul>
    </nav>
  • Fil d'ariane (Breadcrumbs) :
    <nav aria-label="Fil d'ariane">
      <ol>
        <li><a href="/">Accueil</a></li>
        <li><a href="/section">Section</a></li>
        <li aria-current="page">Page Actuelle</li>
      </ol>
    </nav>
  • Labels & descriptions :
    <input id="email" aria-labelledby="label1" aria-describedby="email-help" />
    <label id="label1" for="email">Adresse email</label>
    <div id="email-help">Nous ne partageons jamais votre email.</div>
  • Accessibilité des modales :
    // Bouton déclencheur
          <button id="openModal" aria-haspopup="dialog" aria-controls="modal1">
            Ouvrir la modale
          </button>
    // Structure de la modale
          <div class="modal" id="modal1" role="dialog" aria-modal="true" aria-labelledby="modalTitle" aria-describedby="modalDesc" hidden>
            <div class="modal-content" role="document">
              <h2 id="modalTitle">Abonnez-vous à la newsletter</h2>
              <p id="modalDesc">Restez informé — une fois par mois max.</p>
              <button id="closeModal" aria-label="Fermer la modale">✕</button>
            </div>
          </div>
    // JS avec piège de focus (focus trap) basique
          const openModalBtn = document.getElementById('openModal');
          const closeModalBtn = document.getElementById('closeModal');
          const modal = document.getElementById('modal1');
    
          const focusableElements = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
          let firstFocusable, lastFocusable;
    
          openModalBtn.addEventListener('click', () => {
            modal.hidden = false;
            const focusables = modal.querySelectorAll(focusableElements);
            firstFocusable = focusables[0];
            lastFocusable = focusables[focusables.length - 1];
            firstFocusable.focus();
    
            document.addEventListener('keydown', trapFocus);
          });
    
          closeModalBtn.addEventListener('click', closeModal);
    
          function closeModal() {
            modal.hidden = true;
            openModalBtn.focus();
            document.removeEventListener('keydown', trapFocus);
          }
    
          function trapFocus(e) {
            if (e.key !== 'Tab') return;
    
            if (e.shiftKey) {
              if (document.activeElement === firstFocusable) {
                e.preventDefault();
                lastFocusable.focus();
              }
            } else {
              if (document.activeElement === lastFocusable) {
                e.preventDefault();
                firstFocusable.focus();
              }
            }
          }
  • Alertes d'erreur :
    <div role="alert" aria-live="assertive" class="error-message">
      Veuillez entrer un email valide.
    </div>
  • Tabindex pour le contrôle :
    <div tabindex="0" role="button" aria-pressed="false">Toggle personnalisé</div>
  • Zoom 400% :
    
              /* Commencez mobile-first.
              Considérez le zoom 400% comme équivalent à un petit viewport.
              Si c'est accessible sur petit écran, ça le restera avec un fort zoom.
              Évitez toujours les unités px absolues sur le texte. */
    
            body {
              font-size: 1rem;
              line-height: 1.5;
              padding: 1rem;
            }
    
            img {
              max-width: 100%;
              height: auto;
            }
    
            /* Puis améliorez progressivement pour les grands écrans */
    
            @media (min-width: 600px) {
              body {
                padding: 2rem;
                font-size: 1.125rem;
              }
            }
    
            @media (min-width: 1024px) {
              body {
                padding: 3rem;
                font-size: 1.25rem;
              }
            }