Chapitre 16.3 — Snippets prêts à copier
⏱️ TL;DR — Le code réutilisable des patterns d’accessibilité les plus fréquents : lien d’évitement, classe
.sr-only, bouton icône accessible, hook d’annonce (live region) en React, piège de focus pour modale, et champ de formulaire avec label + erreur liés. Copie, adapte à ton design, teste au clavier et au lecteur d’écran.
Ce que tu trouveras ici
Des extraits directement copiables, chacun précédé de son usage. Ils appliquent ce que le cours a détaillé ; en cas de doute sur le pourquoi, suis le lien vers la partie concernée.
Lien d’évitement (skip link)
Permet de sauter la navigation pour aller droit au contenu (premier Tab de la page). Voir 4.4.
<a href="#contenu" class="skip-link">Aller au contenu principal</a>
<!-- ... navigation ... -->
<main id="contenu" tabindex="-1">…</main>.skip-link {
position: absolute;
left: -9999px;
top: 0;
background: #000;
color: #fff;
padding: 0.75rem 1rem;
z-index: 1000;
}
.skip-link:focus {
left: 0; /* devient visible au focus clavier */
}Classe .sr-only
Texte réservé au lecteur d’écran (contexte, libellé caché). Voir 5.5.
.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;
}Bouton icône accessible
Une icône seule doit avoir un nom accessible. Voir 8.2.
// Option A : aria-label sur le bouton, icône décorative masquée
<button type="button" aria-label="Rechercher">
<SearchIcon aria-hidden="true" focusable="false" />
</button>
// Option B : texte visible pour le lecteur d'écran
<button type="button">
<SearchIcon aria-hidden="true" focusable="false" />
<span className="sr-only">Rechercher</span>
</button>Hook d’annonce (live region) en React
Annoncer un message dynamique sans voler le focus. Voir 6.4.
import { useState, useCallback } from 'react'
export function useAnnounce() {
const [message, setMessage] = useState('')
const announce = useCallback((msg: string) => {
setMessage('') // reset pour re-déclencher
requestAnimationFrame(() => setMessage(msg))
}, [])
const Announcer = () => (
<div aria-live="polite" role="status" className="sr-only">
{message}
</div>
)
return { announce, Announcer }
}
// Usage : const { announce, Announcer } = useAnnounce()
// announce(`${count} cours trouvés`) · <Announcer /> monté une foisPiège de focus (modale) — l’option native d’abord
Le plus simple reste l’élément natif <dialog>, qui gère focus, Échap et fond inerte. Voir 10.2.
<dialog id="confirm">
<h2>Quitter le cours ?</h2>
<p>Ta progression est enregistrée.</p>
<form method="dialog">
<button value="cancel">Annuler</button>
<button value="ok">Quitter</button>
</form>
</dialog>const dlg = document.getElementById('confirm')
document.getElementById('open').addEventListener('click', () => dlg.showModal())
// showModal() : piège le focus, active Échap, rend le reste inerte,
// et le focus revient au déclencheur à la fermeture.Pour un besoin plus complexe en React, préfère une lib éprouvée (Radix, React Aria) — voir 11.4.
Champ de formulaire avec label + erreur liés
Label associé, erreur reliée et annoncée, aria-invalid. Voir 9.3.
function ChampEmail({ erreur }) {
return (
<p>
<label htmlFor="email">Adresse e-mail</label>
<input
id="email"
type="email"
autoComplete="email"
aria-invalid={erreur ? 'true' : undefined}
aria-describedby={erreur ? 'email-erreur' : undefined}
/>
{erreur && (
<span id="email-erreur" role="alert">
{erreur}
</span>
)}
</p>
)
}🧭 Sur A11yLearn — Ces snippets vivent dans la lib partagée d’A11yLearn :
<SkipLink>,.sr-only,<IconButton>,useAnnounce,<Field>. Résultat : un dev qui ajoute un champ ou un bouton icône hérite de l’accessibilité par défaut, sans y penser — c’est le design system accessible en action.
Chapitre suivant : Glossaire & ressources — les termes et les liens de référence.