🏗️ Balises de structure

Structure

<header>

<header> Structure

En-tête d'une page ou d'une section. Contient généralement le logo, le titre principal, la navigation ou une introduction. Peut apparaître plusieurs fois (en-tête de page + en-têtes d'articles). Rôle ARIA implicite : banner (quand enfant direct de body).

Attributs spécifiques
Aucun attribut spécifique — Utilise les attributs globaux (id, class, aria-label...)
Rendu dans la page
🎓 Mon Site
<nav> Structure

Zone de navigation principale ou secondaire du site. Réservée aux liens de navigation importants (menu principal, fil d'Ariane, pagination). Pas pour tous les groupes de liens. Rôle ARIA implicite : navigation.

Bonnes pratiques
aria-label="..." — Nommer chaque <nav> si plusieurs sur la page
aria-current="page" — Sur le lien de la page courante
<main> Structure

Contenu principal et unique de la page. Ce qui distingue cette page de toutes les autres. UN SEUL par page. Ne peut pas être enfant de <article>, <aside>, <footer>, <header> ou <nav>. Rôle ARIA implicite : main.

<footer> Structure

Pied de page d'une page ou d'une section. Contient généralement : copyright, liens légaux, informations de contact, liens secondaires. Comme <header>, peut apparaître dans des articles et sections. Rôle ARIA implicite : contentinfo (quand enfant direct de body).

<article> Structure

Contenu autonome et auto-suffisant : compréhensible seul, hors de son contexte. Exemples : article de blog, post de forum, tweet, commentaire, fiche produit, widget météo. Peut contenir son propre <header>, <footer>, <section>. Rôle ARIA implicite : article.

Rendu

Mon article de blog

Publié le par

Jean Dupont

Le contenu de l'article va ici. Il est compréhensible seul, même hors contexte.

<section> Structure

Regroupe du contenu thématiquement lié. Toujours accompagnée d'un titre. Apparaît dans le plan du document. Utiliser <div> si c'est juste pour le style CSS sans sens sémantique. Rôle ARIA implicite : region (si aria-labelledby ou aria-label).

<aside> Structure

Contenu indirectement lié au contenu principal. En rapport mais pas essentiel : barre latérale, encart, publicité, biographie de l'auteur, liens connexes, note de bas de page. Rôle ARIA implicite : complementary.

Rendu
<div> Structure

Conteneur générique block. Aucun sens sémantique. Utilisé quand aucune autre balise sémantique ne convient. Sert uniquement au style CSS ou au ciblage JavaScript. "div soup" = abus de <div> là où des balises sémantiques seraient plus appropriées. Rôle ARIA implicite : generic.

<span> Structure

Conteneur générique inline. Version inline du <div>. Aucun sens sémantique. Utilisé pour styliser une portion de texte ou la cibler en JavaScript quand aucune autre balise inline ne convient. Exemple : colorer un mot dans une phrase.

Rendu

Ce texte a un mot important mis en évidence.

<address> Structure

Coordonnées de contact de l'auteur ou du propriétaire du document ou d'un article. Peut contenir : adresse postale, email, téléphone, réseaux sociaux, site web. Ne pas utiliser pour des adresses génériques non liées à l'auteur.

Rendu
IntA11Y - Solutions 123 rue du Code, 75001 Paris [email protected] 01 23 45 67 89

📝 Titres et texte

Texte

Titres <h1> à <h6>

<h1> → <h6> Texte

Titres de section, du plus important (h1) au moins important (h6). Créent la hiérarchie du document (plan du document). Les lecteurs d'écran les utilisent pour naviguer. Google les utilise pour comprendre la structure du contenu.

Règles importantes :

  • Un seul <h1> par page (titre principal).
  • Ne pas sauter de niveaux : h1 → h2 → h3 (pas h1 → h3).
  • NE PAS choisir le niveau selon la taille visuelle (utiliser CSS).

Rendu

h1 — Titre principal de la page (un seul)

h2 — Titre de section principale

h3 — Titre de sous-section

h4 — Titre de niveau 4

h5 — Titre de niveau 5
h6 — Titre de niveau 6 (le moins important)
<p> Texte

Paragraphe de texte. Élément block avec espacement automatique en haut et en bas. La balise fermante </p> est techniquement optionnelle mais toujours recommandée. Ne pas utiliser <p> pour des images ou des liens seuls (utiliser <div>).

Rendu

Premier paragraphe. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore.

Deuxième paragraphe. Les navigateurs ajoutent automatiquement une marge entre les paragraphes.

<br> Texte

Saut de ligne dans du texte. Balise auto-fermante (pas de </br>). Utiliser UNIQUEMENT pour des sauts de ligne sémantiquement significatifs (poèmes, adresses, paroles de chanson). NE PAS utiliser <br> pour créer des espacements visuels (utiliser CSS margin/padding à la place).

Rendu

Ligne 1 Ligne 2 (après un saut de ligne) Ligne 3 — Exemple : adresse postale

<hr> Texte

Séparation thématique entre des paragraphes ou sections. Balise auto-fermante. Représente un changement de sujet dans le contenu. Affiché comme une ligne horizontale par défaut. Le style peut être modifié avec CSS. Rôle ARIA implicite : separator.

Rendu

Avant le séparateur thématique.


Après le séparateur — nouveau sujet.

<blockquote> Texte

Citation longue provenant d'une autre source, affichée en bloc. L'attribut cite précise l'URL de la source. Pour une citation courte inline, utiliser <q>. Pour nommer la source, utiliser <cite> à l'intérieur.

Attributs
cite="url"→ URL de la source de la citation
Rendu

"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."

— Martin Fowler
<q> Texte

Citation courte inline (dans une phrase). Le navigateur ajoute automatiquement les guillemets selon la langue du document (lang="fr" → guillemets français « »). Pour une citation longue, utiliser <blockquote>.

Rendu

Comme disait Shakespeare : To be or not to be.

<cite> Texte

Nom d'une œuvre : livre, film, chanson, article, tableau, site web... Affiché en italique par défaut. NE PAS utiliser pour nommer une personne (utiliser pour l'œuvre, pas l'auteur).

Rendu

J'ai lu Le Petit Prince d'Antoine de Saint-Exupéry.

<pre> <code> Texte

<pre> — Texte préformaté : conserve les espaces, les tabulations et les sauts de ligne exactement comme dans le HTML. Police monospace par défaut.

<code> — Fragment de code informatique inline. Police monospace. Souvent utilisé dans du texte courant.

Combo <pre><code> → Bloc de code multilignes (la combinaison standard pour afficher du code).

Rendu

Utilisez console.log() pour déboguer.

function saluer(nom) {
  return "Bonjour, " + nom + " !";
}
console.log(saluer("Alice"));
<kbd> <samp> <var> Texte

Balises techniques liées au code et aux interactions clavier.

Rendu

kbd — Entrée clavier : Appuyez sur Ctrl + C pour copier.

samp — Sortie d'un programme : Erreur 404 : fichier introuvable

var — Variable mathématique : E = m × c²

Mise en forme inline Texte

Balises pour modifier l'apparence ou le sens d'une portion de texte.

Rendu de chaque balise

<strong>Texte important (gras sémantique). Les lecteurs d'écran accentuent la lecture. ≠ <b> (gras visuel pur).

<em>Texte mis en emphase (italique sémantique). Lecteurs d'écran changent le ton. ≠ <i> (italique visuel).

<b>Gras sans importance sémantique (mots-clés, noms de produits).

<i>Italique sans emphase (termes techniques, noms étrangers, pensées).

<u>Soulignement sémantique (fautes d'orthographe, noms propres chinois). Éviter car ressemble à un lien.

<s>[début texte barré] Texte barré / obsolète [fin texte barré] (prix réduit, ancienne version).

<del>Texte supprimé (modification de document, WCAG accessible).

<ins>Texte inséré (contenu ajouté à un document).

<mark>Texte surligné (résultat de recherche, passage pertinent).

<small>Texte de petite taille (mentions légales, copyright, commentaires).

<sub> — H2O — Indice inférieur (formules chimiques, notes de bas de page).

<sup> — E=mc2 — Exposant supérieur (puissances, notes de renvoi).

<abbr>HTML — Abréviation avec définition au survol (title obligatoire).

<dfn>HTML — Définition d'un terme (première occurrence).

<time> — Publié le — Date/heure machine-readable.

<wbr> — LongmotSansEspace — Opportunité de saut de ligne (URL longues).

<bdi>نص عربي — Isolement bidirectionnel (texte RTL dans texte LTR).

<bdo>Texte inversé — Direction de texte forcée (dir="rtl" ou "ltr").

<ruby> <rt> <rp>(kan) — Annotations phonétiques (japonais, chinois).

<data>Produit A — Valeur machine associée à du contenu lisible.

<output> — Résultat : 42 — Résultat d'un calcul ou d'une action.

📋 Listes

Listes

<ul> <ol> <dl>

<ul> Liste

Liste non ordonnée (unordered list). L'ordre des éléments n'a pas d'importance. Affichée avec des puces par défaut. Ne peut contenir que des <li> comme enfants directs. Utiliser quand les items sont équivalents et interchangeables.

Rendu
  • Pommes
  • Bananes
  • Agrumes (liste imbriquée)
    • Oranges
    • Citrons
<ol> Liste

Liste ordonnée (ordered list). L'ordre est important. Affichée avec des numéros par défaut. Exemples : étapes d'une recette, classement, procédure.

Attributs
type→ "1" (1,2,3), "a" (a,b,c), "A" (A,B,C), "i" (i,ii,iii), "I" (I,II,III)
start="5"→ Commence à partir de 5
reversed→ Compte à rebours
Rendu
  1. Préchauffer le four à 180°C
  2. Mélanger les ingrédients
  3. Enfourner 30 minutes
  1. Troisième élément (commence à C)
  2. Quatrième (D)
<li> Liste

Élément de liste (list item). Enfant direct de <ul>, <ol> ou <menu>. Peut contenir n'importe quel contenu (texte, images, d'autres listes...).

Attribut
value="N"→ Définit la valeur numérique de cet item (dans <ol> uniquement)
<dl> <dt> <dd> Liste

Liste de définitions (description list). Paires terme/définition. <dl> — Conteneur de la liste de définitions. <dt> — Terme à définir (definition term). <dd> — Définition du terme (definition description). Un <dt> peut avoir plusieurs <dd>. Plusieurs <dt> peuvent partager un <dd>. Utilisé pour glossaires, FAQ, métadonnées.

Rendu
HTML
HyperText Markup Language — Langage de balisage pour structurer le contenu web.
CSS
Cascading Style Sheets — Langage de présentation pour styliser les pages HTML.
JavaScript
Langage de programmation pour rendre les pages web interactives.
Utilisé aussi côté serveur avec Node.js.
<menu> Liste

Liste de commandes ou d'options (sémantiquement un menu d'actions). Similaire à <ul> mais sémantiquement destiné aux interfaces (barres d'outils, menus contextuels). Contient des <li> avec des <button> ou <a> à l'intérieur.

Rendu
  • 🔗 Liens

    Lien

    <a> — Hyperlien

    <a> Lien

    Hyperlien (anchor). Élément fondamental du Web. Peut lier vers : une autre page, une ancre (#id), un email, un téléphone, un fichier, un fragment JavaScript. Rôle ARIA implicite : link. Utiliser <a href> pour naviguer, <button> pour agir.

    Attributs principaux
    href="url"→ Destination du lien (OBLIGATOIRE pour être un lien actif)
    target="_blank"→ Ouvrir dans un nouvel onglet
    target="_self"→ Ouvrir dans le même onglet (défaut)
    target="_parent"→ Ouvrir dans le cadre parent (iframes)
    target="_top"→ Ouvrir dans la fenêtre complète (iframes)
    rel="noopener noreferrer"→ Sécurité OBLIGATOIRE avec target="_blank"
    rel="nofollow"→ Demande aux moteurs de ne pas suivre ce lien (SEO)
    rel="external"→ Indique un lien externe
    download→ Déclenche un téléchargement au lieu de naviguer
    download="nom.pdf"→ Spécifie le nom du fichier téléchargé
    hreflang="en"→ Langue du document cible
    type="application/pdf"→ Type MIME du document cible
    aria-label="..."→ Description accessible (si le texte du lien n'est pas clair)
    aria-current="page"→ Indique la page courante dans une navigation
    Exemples de liens

    🖼️ Images et médias

    Média

    <img> <figure> <picture> <video> <audio>

    <img> Média

    Affiche une image. Balise auto-fermante. L'attribut alt est OBLIGATOIRE pour l'accessibilité (WCAG 1.1.1). Les lecteurs d'écran lisent le texte alt. Si l'image est décorative : alt="" (vide, pas absent).

    Attributs
    src="url"→ Source de l'image (OBLIGATOIRE)
    alt="description"→ Texte alternatif (OBLIGATOIRE, vide si décoratif)
    width="300"→ Largeur en pixels (évite le layout shift)
    height="200"→ Hauteur en pixels (évite le layout shift)
    loading="lazy"→ Chargement différé (images hors écran) — Performance
    loading="eager"→ Chargement immédiat (défaut)
    decoding="async"→ Décodage asynchrone — Performance
    srcset="img-2x.jpg 2x"→ Images haute résolution (écrans Retina)
    sizes="(max-width:768px) 100vw, 50vw"→ Taille d'affichage selon l'écran (avec srcset)
    crossorigin="anonymous"→ Requête CORS pour les images sur autre domaine
    referrerpolicy→ Contrôle l'envoi du Referer header
    ismap→ Image-map côté serveur (rare)
    usemap="#mapname"→ Lie à une <map> côté client
    Rendu
    Paysage généré aléatoirement par picsum.photos
    <figure> <figcaption> Média

    <figure> — Contenu autonome référencé depuis le texte principal : image, graphique, diagramme, code, poème, tableau... Peut être déplacé sans affecter le flux principal.

    <figcaption> — Légende du <figure> (facultative). Premier ou dernier enfant de <figure>.

    Rendu
    Fig. 1 — La balise <figcaption> ajoute une légende accessible à la figure.
    <picture> <source> Média

    <picture> — Conteneur d'images adaptatives. Permet de servir des formats modernes (WebP, AVIF) avec fallback vers JPEG/PNG. Aussi pour le responsive art direction (image différente selon la taille d'écran).

    <source> — Source alternative testée dans l'ordre. Le navigateur choisit la première qui correspond. <img> en dernier = fallback obligatoire.

    Attributs de <source>
    srcset="img.webp"→ URL de l'image source
    type="image/webp"→ Type MIME (permet au navigateur de savoir s'il supporte)
    media="(max-width:768px)"→ Media query pour l'art direction responsive
    Code et rendu
    Image adaptive avec picture et source
    <map> <area> Média

    <map> — Définit une image cliquable avec plusieurs zones. <area> — Zone cliquable dans la map (auto-fermante). shape = rect (rectangle), circle (cercle), poly (polygone), default (tout).

    Rendu (image avec zones cliquables)
    Image avec zones cliquables Zone gauche Zone droite
    <svg> Média

    Scalable Vector Graphics — Images vectorielles embarquées directement dans le HTML. Infiniment zoomables sans perte de qualité. Accessibles (les éléments peuvent avoir aria-label, title, desc). Manipulables par CSS et JavaScript. Meilleur pour : logos, icônes, graphiques, animations.

    Rendu
    Formes géométriques SVG
    <canvas> Média

    Zone de dessin bitmap contrôlée par JavaScript. Utilisé pour : jeux 2D/3D, visualisations de données, effets, retouche photo, animations complexes. Contrairement à SVG : pas accessible, pas scalable, pas de DOM. Le contenu entre les balises = fallback si canvas non supporté.

    Rendu (dessiné par JavaScript)
    Votre navigateur ne supporte pas Canvas.
    <video> Média

    Lecteur vidéo natif HTML5. Plusieurs <source> = compatibilité navigateurs (différents formats supportés). Le texte entre les balises = fallback pour les navigateurs ne supportant pas la vidéo. WCAG : toujours fournir des sous-titres (track kind="subtitles").

    Attributs importants
    src="video.mp4"→ Source directe (ou utiliser <source>)
    controls→ Affiche les contrôles natifs (play/pause/volume...)
    autoplay→ Lecture automatique (nécessite muted pour fonctionner)
    muted→ Son coupé par défaut
    loop→ Lecture en boucle
    poster="img.jpg"→ Image affichée avant la lecture
    preload="auto|metadata|none"→ Stratégie de préchargement
    playsinline→ Lecture dans la page sur iOS (pas plein écran forcé)
    width / height→ Dimensions en pixels
    Code

    ⚠️ Aucune vidéo chargée dans cet exemple — le poster s'affiche.

    <audio> Média

    Lecteur audio natif HTML5. Même principe que <video> mais sans dimensions visuelles. Formats : MP3, OGG, WAV, AAC, FLAC.

    Attributs (mêmes que video sauf poster/width/height)
    controls→ Contrôles natifs (TOUJOURS recommandé pour l'accessibilité)
    autoplay→ Lecture automatique (déconseillé — mauvaise UX et accessibilité)
    Rendu
    <track> Média

    Piste de texte pour <video> et <audio> (sous-titres, légendes, chapitres, descriptions). Format WebVTT (.vtt). WCAG 1.2.2 exige des sous-titres pour toutes les vidéos.

    Valeurs de kind
    subtitles→ Sous-titres (traduction du dialogue)
    captions→ Légendes pour sourds (dialogue + sons)
    descriptions→ Description audio pour malvoyants
    chapters→ Chapitres pour la navigation
    metadata→ Métadonnées pour JavaScript
    <iframe> Embarqué

    Inline Frame — Embarque une autre page web dans la page courante. Utilisé pour : vidéos YouTube/Vimeo, Google Maps, Tweets, formulaires externes, widgets de paiement. Chaque iframe a son propre contexte de navigation (DOM séparé). SÉCURITÉ : sandbox isole le contenu. CSP contrôle les permissions.

    Attributs
    src="url"→ URL de la page à embarquer
    title="description"→ Description du contenu (OBLIGATOIRE pour l'accessibilité)
    width / height→ Dimensions
    loading="lazy"→ Chargement différé (performance)
    sandbox→ Restreint les permissions (sécurité)
    sandbox="allow-scripts allow-same-origin"→ Permissions spécifiques
    allow="camera; microphone"→ Permissions Permissions Policy
    allowfullscreen→ Autorise le plein écran
    referrerpolicy→ Contrôle le Referer envoyé
    Rendu (OpenStreetMap)
    <embed> <object> <param> Embarqué

    Anciens mécanismes d'intégration (Flash, Java, plugins). Aujourd'hui quasi-obsolètes. Remplacés par <video>, <audio>, <iframe>, SVG, Canvas. <embed> — Contenu externe sans fallback possible. <object> — Contenu externe avec fallback (contenu entre les balises). <param> — Paramètre pour <object>.

    📊 Tableaux

    Tableau

    <table> — Données tabulaires

    <table> et toutes ses balises Tableau

    Réservé aux données tabulaires (lignes + colonnes avec relation). NE PAS utiliser pour la mise en page (utiliser CSS Grid/Flexbox). Un tableau mal structuré est incompréhensible pour les lecteurs d'écran.

    Balises du tableau
    <table>→ Conteneur principal du tableau
    <caption>→ Titre/description du tableau (RECOMMANDÉ pour l'accessibilité)
    <thead>→ En-tête du tableau (groupe les lignes d'en-tête)
    <tbody>→ Corps du tableau (groupe les données)
    <tfoot>→ Pied du tableau (totaux, résumé)
    <tr>→ Ligne du tableau (table row)
    <th>→ Cellule d'en-tête (table header) — gras + centré par défaut
    <td>→ Cellule de données (table data)
    <colgroup> <col>→ Groupe et style de colonnes entières
    scope="col|row|colgroup|rowgroup"→ Sur <th> : indique ce que l'en-tête couvre (accessibilité)
    colspan="2"→ La cellule occupe 2 colonnes
    rowspan="3"→ La cellule occupe 3 lignes
    headers="id-th"→ Lie une <td> à son <th> par id (tableaux complexes)
    Rendu
    Comparatif des langages web
    Langage Type Rôle Difficulté
    HTML Balisage Structure
    CSS Style Présentation ⭐⭐
    JavaScript Programmation Interactivité ⭐⭐⭐
    Total : 3 langages fondamentaux du Web

    📋 Formulaires

    Formulaire

    <form> et tous ses éléments

    <form> Formulaire

    Conteneur d'un formulaire interactif. Groupe les champs de saisie et définit comment les données sont envoyées au serveur.

    Attributs principaux
    action="url"→ URL où envoyer les données (vide = page courante)
    method="GET"→ Données dans l'URL (recherche, filtres)
    method="POST"→ Données dans le corps de la requête (données sensibles)
    enctype="multipart/form-data"→ OBLIGATOIRE pour l'envoi de fichiers
    novalidate→ Désactive la validation native du navigateur
    autocomplete="on|off"→ Active/désactive l'autocomplétion
    aria-label="Nom du formulaire"→ Nommer le formulaire (accessibilité)
    <label> Formulaire

    Étiquette d'un champ de formulaire. OBLIGATOIRE pour l'accessibilité (WCAG 1.3.1, RGAA 11.1). Cliquer sur le label active/coche le champ associé. Deux façons de lier : for="id" sur le label + id="id" sur l'input, ou imbriquer l'input dans le label.

    <input type="..."> Formulaire

    Champ de saisie. Balise auto-fermante. Le type détermine l'interface affichée et la validation. Toujours associé à un <label>.

    Tous les types d'input
    checkbox — Cases à cocher (choix multiples)
    radio — Boutons radio (choix unique)

    hidden — Champ invisible envoyé avec le formulaire (ex: token CSRF, ID session).

    Attributs communs des <input> Formulaire
    name="champ"→ Clé envoyée au serveur (OBLIGATOIRE pour la soumission)
    id="champ"→ Identifiant unique pour le label for="" (OBLIGATOIRE pour l'accessibilité)
    value="..."→ Valeur initiale ou valeur envoyée
    placeholder="..."→ Texte indicatif (disparaît à la saisie) — NE REMPLACE PAS le label
    required→ Champ obligatoire (validation native)
    disabled→ Désactivé (non envoyé, non interactif)
    readonly→ Lecture seule (envoyé, non modifiable)
    autofocus→ Focus automatique au chargement (un seul par page)
    autocomplete="..."→ Type de donnée pour l'autocomplétion (name, email, tel...)
    pattern="[A-Z]{3}"→ Expression régulière de validation
    minlength / maxlength→ Longueur min/max du texte
    aria-describedby="id"→ Lie un message d'aide ou d'erreur au champ
    aria-invalid="true"→ Indique un champ invalide aux lecteurs d'écran
    aria-required="true"→ Champ obligatoire (en plus de required)
    form="form-id"→ Lie l'input à un <form> par id (même si hors du form)
    list="datalist-id"→ Suggestions depuis un <datalist>
    <textarea> Formulaire

    Zone de texte multiligne. Redimensionnable par l'utilisateur. Pas d'attribut value — le contenu est entre les balises.

    rows="5"→ Nombre de lignes visibles
    cols="40"→ Largeur en caractères
    resize: none→ En CSS : empêche le redimensionnement
    wrap="hard|soft"→ Comportement du retour à la ligne
    Rendu
    <select> <option> <optgroup> Formulaire

    Liste déroulante de sélection. <select> — Conteneur de la liste. <option> — Élément de la liste. <optgroup> — Groupe d'options avec label.

    multiple→ Permet la sélection multiple (Ctrl+clic)
    size="5"→ Nombre d'options visibles
    selected→ Sur <option> : présélectionné
    disabled→ Sur <option> : option inactive
    value="..."→ Sur <option> : valeur envoyée (si absent, le texte est utilisé)
    Rendu
    <datalist> Formulaire

    Liste de suggestions pour un <input list="id">. Combine la liberté de saisie d'un input avec des suggestions comme un select. L'utilisateur peut taper autre chose que les suggestions.

    Rendu
    <fieldset> <legend> Formulaire

    <fieldset> — Groupe des champs de formulaire liés. Dessine une bordure autour du groupe par défaut. <legend> — Titre/description du groupe (toujours premier enfant de fieldset). OBLIGATOIRE pour l'accessibilité des groupes de radios/checkboxes. Le lecteur d'écran lit la légende avant chaque option du groupe.

    Rendu
    Informations personnelles
    <button> Formulaire

    Bouton interactif. Peut contenir du HTML (texte, images, icônes). Plus flexible que <input type="button">. Rôle ARIA implicite : button. Toujours préciser type= pour éviter les comportements inattendus.

    type="submit"→ Soumet le formulaire parent (DÉFAUT si non précisé dans un form)
    type="reset"→ Réinitialise le formulaire
    type="button"→ Bouton générique (aucun comportement natif, contrôlé par JS)
    disabled→ Désactivé (non cliquable, non focusable)
    form="form-id"→ Lie le bouton à un formulaire par id
    formaction="url"→ Surcharge l'action du formulaire pour ce bouton
    formmethod="POST"→ Surcharge la méthode du formulaire
    aria-label="..."→ Si l'icône seule n'est pas explicite
    aria-pressed="true|false"→ État d'un bouton bascule (toggle)
    aria-expanded="true|false"→ État d'un bouton qui ouvre/ferme un contenu
    Rendu
    <progress> <meter> <output> Formulaire

    Éléments de formulaire pour afficher des valeurs.

    <progress value="70" max="100">→ Barre de progression (indéterminée si pas de value)
    <meter value="6" min="0" max="10" low="3" high="8" optimum="9">→ Jauge avec zones (basse/haute/optimale)
    <output name="res" for="a b">→ Résultat d'un calcul (lié aux inputs par for)
    Rendu
    70%
    En cours...
    6/10

    Calcul (a + b = résultat) :

    8
    Formulaire complet d'exemple Formulaire

    Un formulaire d'inscription complet avec toutes les bonnes pratiques.

    Rendu
    Informations de compte
    Entre 2 et 50 caractères.
    Minimum 8 caractères.
    Votre niveau

    Champs obligatoires

    ✨ Balises spéciales

    Spécial

    <details> <dialog> <template> <slot>

    <details> <summary> Spécial

    <details> — Widget d'accordéon natif HTML. Le contenu est masqué/affiché au clic sans JavaScript. L'attribut open l'ouvre par défaut. <summary> — Premier enfant de details, toujours visible, sert de titre cliquable pour ouvrir/fermer.

    Rendu (cliquer pour ouvrir)
    📖 Qu'est-ce que le HTML ?

    HTML (HyperText Markup Language) est le langage de balisage standard pour créer des pages web. Il définit la structure et le sens du contenu web.

    ✅ CSS — déjà ouvert par défaut (attribut open)

    CSS (Cascading Style Sheets) est le langage de style utilisé pour décrire la présentation d'un document HTML.

    <dialog> Spécial

    Boîte de dialogue / modale native HTML5. Gère automatiquement : focus trap, accessibilité ARIA, arrière-plan modal (::backdrop). Ouverture : dialog.showModal() (modale) ou dialog.show() (non-modale). Fermeture : bouton avec method="dialog" dans un <form> interne. L'attribut open l'affiche (préférer la méthode JS). Rôle ARIA implicite : dialog.

    Rendu (cliquer le bouton)

    Confirmation

    Êtes-vous sûr de vouloir effectuer cette action ?

    <template> <slot> Spécial

    <template> — Contenu HTML inerte (non rendu, non exécuté). Stocke du HTML réutilisable activable par JavaScript via template.content.cloneNode(true). Utilisé pour les Web Components et la génération dynamique.

    <slot> — Emplacement de contenu dans un Shadow DOM (Web Components). Permet d'injecter du contenu depuis l'extérieur du composant.

    Démo
    <script> <noscript> Script

    <script> — Intègre ou charge du JavaScript. Dans le body = exécuté quand rencontré. Toujours en bas du <body> ou avec defer/async dans le head, pour ne pas bloquer l'affichage de la page.

    <noscript> — Contenu de fallback affiché si JavaScript est désactivé. Dans le body : peut contenir n'importe quel HTML.

    src="script.js"→ Fichier JS externe
    defer→ Exécution après parsing HTML complet
    async→ Exécution dès téléchargement (sans ordre garanti)
    type="module"→ Module ES6 (import/export)
    integrity="sha384-..."→ Vérification d'intégrité (SRI) pour fichiers CDN
    crossorigin="anonymous"→ CORS pour les scripts externes
    Autres balises du <head> Méta
    <meta http-equiv="refresh" content="5;url=/page">→ Redirection automatique après 5 secondes
    <meta http-equiv="X-UA-Compatible" content="IE=edge">→ Mode de rendu Internet Explorer (legacy)
    <meta name="color-scheme" content="light dark">→ Thèmes supportés (clair/sombre)
    <meta name="generator" content="WordPress">→ Outil utilisé pour générer la page
    <meta name="referrer" content="no-referrer">→ Politique de Referrer par défaut
    <meta name="format-detection" content="telephone=no">→ Empêche iOS de transformer les numéros en liens
    <link rel="pingback" href="/xmlrpc.php">→ URL de pingback (WordPress, blogs)
    <link rel="search" href="/opensearch.xml">→ Plugin de recherche OpenSearch
    <link rel="next" href="/page-2">→ Page suivante (pagination)
    <link rel="prev" href="/page-1">→ Page précédente (pagination)
    Attributs globaux (sur TOUTES les balises) Global

    Ces attributs peuvent être utilisés sur n'importe quelle balise HTML.

    id="identifiant"→ Identifiant UNIQUE sur la page. Cible CSS (#id), JS, ancres (#id)
    class="nom"→ Classe(s) CSS (séparées par des espaces). Non unique
    style="color:red"→ Style CSS inline (priorité maximale, éviter sauf cas particuliers)
    title="info"→ Info-bulle au survol. Texte descriptif supplémentaire
    lang="fr"→ Langue du contenu de CET élément (si différente du document)
    dir="ltr|rtl|auto"→ Direction du texte de cet élément
    tabindex="0"→ 0 = focusable dans l'ordre naturel | -1 = focusable par JS seulement | N = ordre personnalisé
    hidden→ Masque l'élément (display:none) et le retire de l'accessibilité
    contenteditable="true"→ Rend le contenu éditable par l'utilisateur
    draggable="true"→ Rend l'élément glissable (drag and drop)
    spellcheck="true"→ Active la vérification orthographique
    translate="yes|no"→ Autorise/interdit la traduction automatique
    accesskey="k"→ Raccourci clavier (Alt+k ou Ctrl+k selon OS)
    data-mon-attribut="valeur"→ Attribut personnalisé lu par JS via dataset.monAttribut
    aria-label="..."→ Nom accessible (lecteur d'écran) — remplace le texte visible
    aria-labelledby="id"→ Nom accessible via un autre élément
    aria-describedby="id"→ Description accessible via un autre élément
    aria-hidden="true"→ Masqué des lecteurs d'écran (décoratif)
    aria-live="polite|assertive"→ Zone mise à jour dynamiquement annoncée aux lecteurs d'écran
    role="..."→ Rôle ARIA (button, link, dialog, alert, img, heading...) si balise sémantique impossible
    inert→ Rend l'élément et tous ses descendants non interactifs et invisibles à l'accessibilité
    popover→ (Nouveau) Popover natif HTML (tooltip, dropdown) sans JS

    📌 Règles d'or à retenir

    Résumé

    Les règles fondamentales

    ✅ Sémantique

    • Un seul <h1> par page
    • Hiérarchie h1→h2→h3 sans sauter
    • Un seul <main> par page
    • <article> = contenu autonome
    • <section> = toujours avec un titre
    • <nav> = navigations principales seulement
    • <div>/<span> = dernier recours

    ♿ Accessibilité

    • lang="fr" sur <html>
    • alt="" sur chaque <img>
    • <label for> sur chaque champ
    • Contraste texte ≥ 4.5:1 (WCAG)
    • Skip link en premier
    • <fieldset>+<legend> pour radios/checkbox
    • Sous-titres pour vidéos

    🔗 Liens et boutons

    • <a href> = naviguer
    • <button> = agir
    • type="button" toujours sur <button>
    • rel="noopener noreferrer" + _blank
    • aria-label si texte pas clair
    • aria-current="page" sur lien actif

    ⚡ Performance

    • loading="lazy" sur les images
    • width et height sur <img>
    • <script> en bas du <body>
    • defer ou async sur les scripts
    • preconnect pour les polices
    • <picture> pour les formats modernes

    ♿ Accessibilité — WCAG, RGAA & ARIA

    Fondamentaux

    Qu'est-ce que l'accessibilité web ?

    Définition Concept

    L'accessibilité web (a11y) consiste à concevoir des sites et applications utilisables par toutes les personnes, quelles que soient leurs capacités physiques, cognitives ou technologiques.

    👁️ Visuelles
    • Cécité (lecteur d'écran)
    • Malvoyance (zoom, contraste)
    • Daltonisme (couleur seule insuffisante)
    👂 Auditives
    • Surdité (sous-titres)
    • Malentendance (transcription)
    🖐️ Motrices
    • Clavier seul (pas de souris)
    • Commande vocale
    • Tremblement (cibles larges)
    🧠 Cognitives
    • Dyslexie (police adaptée)
    • TDAH (clarté, structure)
    • Épilepsie (animations)
    WCAG — Web Content Accessibility Guidelines Standard international

    Recommandations du W3C pour l'accessibilité des contenus web. Version actuelle : WCAG 2.2 (2023). Organisées autour de 4 principes (POUR) :

    P — Perceptible

    Le contenu doit être présentable de façon perceptible par les sens. Textes alternatifs, sous-titres, contrastes suffisants.

    O — Utilisable

    Les composants d'interface et la navigation doivent être utilisables. Navigation clavier, pas de clignotement dangereux.

    U — Compréhensible

    Le contenu et l'interface doivent être compréhensibles. Langue déclarée, formulaires explicites, comportement prévisible.

    R — Robuste

    Le contenu doit être interprétable par les technologies d'assistance. HTML valide, ARIA correct, compatibilité navigateurs.

    3 niveaux de conformité :

    A (minimum)→ Critères de base. Sans eux, certains utilisateurs ne peuvent PAS accéder au contenu.
    AA (recommandé)→ Niveau visé par la loi française (RGAA) et la plupart des obligations légales mondiales.
    AAA (excellence)→ Niveau le plus élevé. Difficile à atteindre sur l'ensemble d'un site. Objectif pour certains contenus.
    RGAA — Référentiel Général d'Amélioration de l'Accessibilité Référentiel français

    Déclinaison française des WCAG 2.1 AA, publiée par la DINUM. Version actuelle : RGAA 4.1 (2021). Obligatoire en France pour : services publics, établissements publics, entreprises de +250M€ de CA. Basé sur des tests techniques précis organisés en 13 thématiques.

    1. Images
    2. Cadres
    3. Couleurs
    4. Multimédia
    5. Tableaux
    6. Liens
    7. Scripts
    8. Éléments obligatoires
    9. Structuration
    10. Présentation
    11. Formulaires
    12. Navigation
    13. Consultation
    WCAG 2.2

    Critères essentiels à connaître

    Principe 1 — Perceptible WCAG
    1.1 — Alternatives textuelles
    1.1.1 — ATout contenu non textuel (image, icône, graphique) doit avoir une alternative textuelle. alt="description" sur <img>. aria-label sur <svg>. alt="" si décoratif.
    1.2 — Médias temporels
    1.2.1 — AAudio/vidéo pré-enregistré : sous-titres ou transcription textuelle.
    1.2.2 — ASous-titres pour toutes les vidéos pré-enregistrées. <track kind="captions">
    1.2.3 — AAudiodescription ou alternative textuelle pour les vidéos.
    1.2.5 — AAAudiodescription pour toutes les vidéos pré-enregistrées. <track kind="descriptions">
    1.3 — Adaptabilité
    1.3.1 — AInformation et relations : la structure est transmissible via le code (titres, listes, tableaux, formulaires). HTML sémantique + ARIA.
    1.3.2 — AOrdre séquentiel : l'ordre de lecture du DOM correspond à l'ordre visuel.
    1.3.3 — ACaractéristiques sensorielles : les instructions ne reposent pas uniquement sur la forme, couleur ou position ("cliquez sur le bouton rouge à droite" ← insuffisant).
    1.3.4 — AAOrientation : le contenu n'est pas limité à une orientation (portrait/paysage). Ne pas bloquer l'orientation.
    1.3.5 — AAIdentification de l'objet de saisie : utiliser autocomplete avec les valeurs standardisées (name, email, tel...).
    1.4 — Distinguable
    1.4.1 — AUtilisation de la couleur : la couleur seule ne suffit pas à transmettre une information. Toujours doubler d'un autre indicateur (icône, texte, motif).
    1.4.2 — AContrôle du son : tout son automatique > 3s doit pouvoir être coupé.
    1.4.3 — AAContraste du texte : ratio minimum 4.5:1 pour texte normal, 3:1 pour grand texte (>18pt ou >14pt gras).
    1.4.4 — AARedimensionnement du texte : texte redimensionnable jusqu'à 200% sans perte de contenu. Utiliser rem/em, pas px fixe.
    1.4.5 — AAImages de texte : ne pas utiliser d'images pour afficher du texte (sauf logotypes).
    1.4.10 — AAReflow : à 400% de zoom, le contenu doit rester lisible sans scroll horizontal (responsive).
    1.4.11 — AAContraste des composants non textuels : ratio 3:1 pour les bordures d'input, icônes fonctionnelles, graphiques.
    1.4.12 — AAEspacement du texte : le contenu reste lisible si on applique : line-height ≥1.5, letter-spacing ≥0.12em, word-spacing ≥0.16em. Ne pas bloquer ces propriétés.
    1.4.13 — AAContenu au survol/focus : les tooltips et popups doivent être ignorables, survolables, et persistants.
    Principe 2 — Utilisable WCAG
    2.1 — Accessibilité au clavier
    2.1.1 — AToutes les fonctionnalités sont accessibles au clavier (Tab, Entrée, Espace, flèches, Échap).
    2.1.2 — APas de piège clavier : le focus peut toujours quitter un composant (modales : Échap, focus trap documenté).
    2.1.4 — ARaccourcis clavier d'un seul caractère : doivent pouvoir être désactivés ou reconfigurés.
    2.2 — Délais suffisants
    2.2.1 — ADélais : tout délai doit pouvoir être désactivé, ajusté (×10) ou prolongé (×20).
    2.2.2 — APause, stop, masquer : tout contenu animé, clignotant ou défilant doit pouvoir être mis en pause.
    2.3 — Crises et réactions physiques
    2.3.1 — APas plus de 3 flashs par seconde (risque d'épilepsie photosensible).
    2.3.3 — AAAprefers-reduced-motion CSS : respecter le paramètre système qui demande de réduire les animations.
    2.4 — Navigation
    2.4.1 — ABypass blocks : skip link pour sauter la navigation répétitive. <a href="#main">Aller au contenu</a>
    2.4.2 — ATitre de page : <title> descriptif et unique pour chaque page.
    2.4.3 — AOrdre de focus : l'ordre de tabulation est logique et préserve le sens. Éviter tabindex > 0.
    2.4.4 — AObjet d'un lien dans son contexte : chaque lien a un texte compréhensible. Pas de "cliquez ici" seul.
    2.4.6 — AAEn-têtes et étiquettes : titres et labels des formulaires sont descriptifs et utiles.
    2.4.7 — AAFocus visible : le composant qui a le focus clavier est TOUJOURS visuellement identifiable. :focus-visible { outline: 3px solid ... }
    2.4.11 — AAFocus non obscurci : quand un composant reçoit le focus, il n'est pas entièrement masqué (sticky header...).
    2.4.12 — AAAFocus non obscurci (renforcé) : le composant focusé n'est pas du tout masqué.
    2.5 — Modalités d'entrée
    2.5.3 — AÉtiquette dans le nom : le nom accessible contient le texte visible (aria-label inclut le texte du bouton).
    2.5.4 — AActivation par le mouvement : fonctionnalités activables par geste ou mouvement ont une alternative.
    2.5.5 — AATaille de la cible : zone cliquable minimum recommandée de 44×44 px. min-height: 44px; min-width: 44px
    2.5.7 — AAMouvements de glissement : toute action nécessitant un glissement peut être réalisée autrement.
    2.5.8 — AATaille de la cible (minimum) : taille cible ≥ 24×24 px (critère plus strict que 2.5.5 introduit en WCAG 2.2).
    Principe 3 — Compréhensible WCAG
    3.1 — Lisible
    3.1.1 — ALangue de la page : <html lang="fr"> obligatoire. Permet aux synthèses vocales de choisir la bonne voix.
    3.1.2 — AALangue d'un passage : <span lang="en">Hello world</span> pour les passages dans une autre langue.
    3.2 — Prévisible
    3.2.1 — APas de changement de contexte au focus : recevoir le focus ne soumet pas un formulaire ou ne change pas la page.
    3.2.2 — APas de changement de contexte à la saisie : changer un champ ne déclenche pas une action inattendue sans avertissement.
    3.2.3 — AANavigation cohérente : les composants répétés (nav, recherche...) sont dans le même ordre relatif sur toutes les pages.
    3.2.4 — AAIdentification cohérente : les composants avec la même fonction sont identifiés de façon cohérente.
    3.2.6 — AAide à la navigation cohérente : les mécanismes d'aide (contact, FAQ...) apparaissent dans le même ordre.
    3.3 — Assistance à la saisie
    3.3.1 — AIdentification des erreurs : les erreurs sont détectées et décrites à l'utilisateur par du texte (pas seulement rouge). aria-invalid="true" + message d'erreur.
    3.3.2 — AÉtiquettes et instructions : les champs de formulaire ont des labels clairs et les formats attendus sont indiqués.
    3.3.3 — AASuggestion après une erreur : quand possible, suggérer comment corriger l'erreur.
    3.3.4 — AAPrévention des erreurs : pour les soumissions importantes (commandes, données personnelles), permettre de réviser, corriger, confirmer ou annuler.
    3.3.7 — ARedondance de l'authentification : pas de test cognitif (CAPTCHA) pour se connecter, sauf alternative fournie.
    Principe 4 — Robuste WCAG
    4.1 — Compatible
    4.1.1 — AHTML valide : pas d'erreurs de parsing. IDs uniques. Balises correctement imbriquées et fermées. Passer le validateur W3C.
    4.1.2 — ANom, rôle, valeur : tous les composants d'interface ont un nom, un rôle et une valeur accessibles et modifiables programmatiquement. C'est le critère qui justifie tout ARIA.
    4.1.3 — AAMessages d'état : les messages importants (succès, erreur, chargement) sont annoncés sans recevoir le focus. role="alert" ou aria-live.
    ARIA

    WAI-ARIA — Accessible Rich Internet Applications

    Qu'est-ce que ARIA ? Concept

    ARIA est un ensemble d'attributs HTML supplémentaires qui donnent des informations sémantiques aux technologies d'assistance (lecteurs d'écran, commande vocale) quand le HTML natif ne suffit pas.

    ⚠️ Règle d'or ARIA — "No ARIA is better than bad ARIA"
    1. Utiliser d'abord le HTML sémantique natif. Un <button> est préférable à <div role="button">.
    2. Ne pas changer le rôle natif sans raison. Mettre role="button" sur un <a> est rarement justifié.
    3. Tout widget ARIA interactif doit être utilisable au clavier. Si vous ajoutez role="button", gérer Entrée et Espace en JS.
    4. Les éléments visibles interactifs doivent avoir un nom accessible.
    5. Tester avec de vrais lecteurs d'écran (NVDA, JAWS, VoiceOver, TalkBack).
    role="..." — Rôles ARIA ARIA

    Définit la nature sémantique d'un élément pour les technologies d'assistance. Les balises HTML ont déjà des rôles implicites (voir tableau ci-dessous). N'utiliser role que quand le HTML natif est insuffisant.

    Rôles implicites des balises HTML (ne pas les redéfinir)

    Balise HTML Rôle ARIA implicite Condition
    <header>bannerEnfant direct de <body>
    <footer>contentinfoEnfant direct de <body>
    <main>mainToujours
    <nav>navigationToujours
    <aside>complementaryToujours
    <section>regionSi aria-labelledby ou aria-label
    <article>articleToujours
    <form>formSi aria-label ou aria-labelledby
    <button>buttonToujours
    <a href>linkAvec href
    <a> (sans href)genericSans href
    <h1>–<h6>headingToujours
    <ul>, <ol>listToujours
    <li>listitemToujours
    <img>imgAvec alt non vide
    <img alt="">presentationalt vide = décoratif
    <table>tableToujours
    <input type="text">textboxToujours
    <input type="checkbox">checkboxToujours
    <input type="radio">radioToujours
    <select>combobox / listboxSelon contexte
    <dialog>dialogToujours
    <details>groupToujours
    <summary>buttonToujours
    <div>, <span>genericAucun rôle sémantique

    Rôles ARIA à utiliser manuellement (sur des <div> ou éléments non natifs)

    Landmarks (points de repère de navigation)
    role="banner"→ En-tête de site (sur <div> si <header> impossible)
    role="navigation"→ Navigation (sur <div> si <nav> impossible)
    role="main"→ Contenu principal (sur <div> si <main> impossible)
    role="complementary"→ Contenu secondaire (sur <div> si <aside> impossible)
    role="contentinfo"→ Pied de page (sur <div> si <footer> impossible)
    role="search"→ Formulaire/zone de recherche (n'a pas de balise HTML native)
    role="region"→ Section nommée (avec aria-label ou aria-labelledby)
    role="form"→ Formulaire nommé (sur <div> si <form> impossible)
    Widgets interactifs
    role="button"→ Bouton (préférer <button>). Doit gérer clic + Entrée + Espace en JS.
    role="link"→ Lien (préférer <a href>). Doit gérer clic + Entrée en JS.
    role="checkbox"→ Case à cocher (préférer <input type="checkbox">).
    role="radio"→ Bouton radio (préférer <input type="radio">).
    role="combobox"→ Champ de saisie avec liste de suggestions (autocomplete custom).
    role="listbox"→ Liste d'options sélectionnables (select custom).
    role="option"→ Option dans un listbox ou combobox.
    role="menubar"→ Barre de menu horizontale (type menu application).
    role="menu"→ Menu déroulant (liste de commandes).
    role="menuitem"→ Élément de menu.
    role="menuitemcheckbox"→ Élément de menu avec état coché.
    role="menuitemradio"→ Élément de menu avec sélection exclusive.
    role="tab"→ Onglet dans un système d'onglets.
    role="tablist"→ Conteneur des onglets.
    role="tabpanel"→ Panneau de contenu associé à un onglet.
    role="slider"→ Curseur de valeur (préférer <input type="range">).
    role="spinbutton"→ Champ numérique avec flèches (préférer <input type="number">).
    role="switch"→ Interrupteur on/off (comme aria-pressed mais sémantique "switch").
    role="tree"→ Arborescence (treeview, explorer de fichiers).
    role="treeitem"→ Nœud dans une arborescence.
    role="grid"→ Grille interactive (tableau avec cellules éditables/sélectionnables).
    role="gridcell"→ Cellule dans un grid.
    role="scrollbar"→ Barre de défilement custom.
    role="separator"→ Séparateur (focusable si interactif, sinon préférer <hr>).
    role="toolbar"→ Barre d'outils (groupe de boutons liés).
    role="tooltip"→ Infobulle. Associé au déclencheur via aria-describedby.
    Zones de contenu
    role="alert"→ Message urgent annoncé immédiatement par les lecteurs d'écran (erreur, message critique). Équivalent aria-live="assertive" + aria-atomic="true".
    role="status"→ Message d'état non urgent (confirmation, info). Équivalent aria-live="polite".
    role="log"→ Zone de log (chat, historique). Nouvelles entrées annoncées poliment.
    role="marquee"→ Contenu défilant en temps réel (cours de bourse). Rarement annoncé.
    role="timer"→ Minuteur ou horloge. Annoncé périodiquement.
    role="progressbar"→ Barre de progression (préférer <progress>).
    role="dialog"→ Boîte de dialogue modale (préférer <dialog>).
    role="alertdialog"→ Modale urgente (erreur critique, confirmation destructive). Focus forcé dessus.
    Document / Structure
    role="heading"→ Titre. Toujours avec aria-level="1" à "6". Préférer <h1>-<h6>.
    role="list"→ Liste. Utiliser si list-style:none retire le rôle natif sur <ul>.
    role="listitem"→ Élément de liste. Avec role="list" parent.
    role="img"→ Image (groupe d'éléments représentant une image, ex: SVG complexe ou icône font).
    role="figure"→ Contenu illustratif (préférer <figure>).
    role="group"→ Groupe d'éléments liés sans landmark (préférer <fieldset> pour les formulaires).
    role="definition"→ Définition d'un terme (avec role="term" sur le terme).
    role="term"→ Terme à définir (comme <dt>).
    role="blockquote"→ Citation longue (préférer <blockquote>).
    role="code"→ Extrait de code (préférer <code>).
    role="math"→ Expression mathématique (avec MathML).
    role="note"→ Note ou parenthèse dans le document.
    role="presentation"→ L'élément est purement décoratif, son rôle est supprimé. Synonyme de role="none".
    role="none"→ Supprime le rôle sémantique natif de l'élément. Utiliser avec précaution.
    aria-* — Propriétés et états ARIA

    Les attributs aria-* se divisent en deux catégories : propriétés (valeurs stables, rarement modifiées) et états (valeurs changeant dynamiquement via JavaScript).

    Nommage accessible (nom de l'élément)
    aria-label="Fermer"→ Nom textuel direct. Remplace le contenu visible pour les lecteurs d'écran. Sur bouton avec icône seule, sur input sans label visible.
    aria-labelledby="id-titre"→ Nom via un autre élément (pointe vers son id). Plus fort que aria-label. Sur dialog, section, fieldset, form. Peut référencer plusieurs ids : "id1 id2".
    aria-describedby="id-msg"→ Description complémentaire via un autre élément. Sur input (message d'aide/erreur), dialog (description sous le titre). Annoncé après le nom.
    aria-description="texte"→ Description textuelle directe (alternative à aria-describedby sans créer d'élément DOM).
    aria-details="id"→ Lien vers une description étendue (glossaire, graphique complexe, instructions longues).
    Visibilité et masquage
    aria-hidden="true"→ Masque l'élément et tous ses descendants des technologies d'assistance. Pour les décorations, icônes redondantes, contenus dupliqués.
    aria-hidden="false"→ Restaure la visibilité (rarement utile, préférer retirer l'attribut).
    États interactifs
    aria-expanded="true|false"→ État ouvert/fermé d'un accordéon, menu déroulant, liste de suggestions. Sur le bouton déclencheur. "true" = contenu visible.
    aria-pressed="true|false|mixed"→ État d'un bouton bascule (toggle button). true = actif, false = inactif, mixed = état intermédiaire.
    aria-checked="true|false|mixed"→ État d'une checkbox ou radio custom. mixed = case indéterminée (groupe partiellement coché).
    aria-selected="true|false"→ Élément sélectionné dans listbox, tabs, grid, treeview.
    aria-current="page|step|location|date|time|true"→ Élément courant dans un ensemble. "page" = lien de la page active. "step" = étape courante d'un wizard.
    aria-disabled="true|false"→ Composant désactivé mais toujours focusable (différent de disabled HTML qui retire du tabindex). Pour indiquer l'état sans retirer la possibilité de focus.
    aria-busy="true|false"→ Zone en cours de chargement. "true" = les lecteurs d'écran attendent que le chargement soit terminé avant d'annoncer les changements.
    aria-grabbed="true|false"→ Élément en cours de glissement (drag and drop). Déprécié en ARIA 1.1, utiliser aria-grabbed + aria-dropeffect avec précaution.
    Contraintes et validation de formulaire
    aria-required="true"→ Champ obligatoire (en complément de required HTML). Annoncé "obligatoire" par les lecteurs d'écran.
    aria-invalid="true|false|grammar|spelling"→ Champ invalide. "true" = erreur générique. "grammar" = erreur grammaticale. "spelling" = faute d'orthographe. Associer à un message d'erreur via aria-describedby.
    aria-readonly="true"→ Champ en lecture seule (en complément de readonly HTML).
    aria-multiselectable="true"→ Plusieurs éléments peuvent être sélectionnés dans un listbox ou grid.
    aria-multiline="true"→ Champ de texte multiligne (sur role="textbox").
    Valeurs et plages
    aria-valuenow="50"→ Valeur actuelle d'un slider, progressbar, spinbutton.
    aria-valuemin="0"→ Valeur minimale.
    aria-valuemax="100"→ Valeur maximale.
    aria-valuetext="Moyen"→ Texte lisible de la valeur (quand le nombre seul n'est pas suffisant. Ex: aria-valuenow="2" aria-valuetext="Mardi").
    Structure et relations
    aria-controls="id-contenu"→ Indique quel élément ce widget contrôle (bouton burger → nav, bouton tab → tabpanel).
    aria-owns="id1 id2"→ Déclare des enfants qui ne sont pas dans le DOM (éléments rendus hors du parent pour des raisons CSS/z-index).
    aria-flowto="id"→ Ordre de lecture alternatif (quand l'ordre DOM ne correspond pas à l'ordre logique).
    aria-level="2"→ Niveau hiérarchique. Sur role="heading" : niveau du titre (1-6). Sur role="treeitem" : niveau dans l'arborescence.
    aria-setsize="5"→ Nombre total d'éléments dans le groupe (quand non évident). Sur les onglets, options, items de liste paginée.
    aria-posinset="2"→ Position de l'élément dans son groupe (avec aria-setsize). "Élément 2 sur 5".
    aria-colcount / aria-rowcount→ Nombre total de colonnes/lignes dans un grid ou tableau (quand le DOM n'en affiche qu'une partie).
    aria-colindex / aria-rowindex→ Index de la colonne/ligne dans le tableau complet (tableaux virtualisés).
    aria-colspan / aria-rowspan→ Nombre de colonnes/lignes que couvre une cellule (dans un grid ARIA).
    aria-sort="ascending|descending|none|other"→ Tri d'une colonne de tableau. Sur le <th> de la colonne triée.
    Zones de mise à jour dynamique (Live Regions)
    aria-live="polite"→ Annonce les mises à jour quand le lecteur d'écran a terminé sa lecture en cours. Pour les notifications non urgentes (succès, mise à jour de données).
    aria-live="assertive"→ Annonce immédiatement, en interrompant la lecture en cours. Pour les alertes urgentes, messages d'erreur critiques. Utiliser avec parcimonie.
    aria-live="off"→ Désactive les annonces (défaut). Utile pour réactiver dynamiquement.
    aria-atomic="true"→ Annonce TOUT le contenu de la zone (même ce qui n'a pas changé) à chaque mise à jour. Plutôt que seulement la partie modifiée.
    aria-atomic="false"→ Annonce uniquement les parties modifiées (défaut).
    aria-relevant="additions removals text"→ Quels types de changements déclencher des annonces. "additions" = ajouts, "removals" = suppressions, "text" = modifications de texte. Défaut : "additions text".
    Keyboard shortcuts et aide
    aria-keyshortcuts="Alt+Shift+A"→ Raccourci clavier associé au composant. Annoncé par les lecteurs d'écran.
    aria-roledescription="Carrousel"→ Description du rôle en langage naturel (remplace le rôle technique par un terme métier). Ex: role="group" + aria-roledescription="Diapositive".
    aria-placeholder="JJ/MM/AAAA"→ Indication courte sur le format attendu (sur role="textbox" custom). Préférer <input placeholder>.
    aria-errormessage="id-erreur"→ Pointe vers l'élément contenant le message d'erreur détaillé. Utiliser avec aria-invalid="true".
    aria-modal="true"→ Indique aux lecteurs d'écran que le reste de la page est inerte pendant que la modale est ouverte. Sur role="dialog".
    aria-haspopup="menu|listbox|tree|grid|dialog|true"→ Le composant peut ouvrir un popup. "true" ou "menu" = menu. Annoncé "a un sous-menu" ou "ouvre une liste".
    aria-autocomplete="none|list|inline|both"→ Comportement d'autocomplétion d'un combobox ou textbox. "list" = liste de suggestions, "inline" = complétion dans le champ, "both" = les deux.
    aria-activedescendant="id-focused-item"→ ID de l'élément focusé dans un widget composite (listbox, combobox, grid). Le focus DOM reste sur le conteneur mais aria indique l'item actif.
    aria-colheader / aria-rowheader→ Indique que la cellule est un en-tête de colonne ou de ligne (dans un grid ARIA).
    Patterns

    Patterns ARIA courants avec code

    Pattern : Skip Link (Lien d'évitement) WCAG 2.4.1 — A

    Premier élément focusable de la page. Invisible jusqu'au focus clavier. Permet de sauter la navigation principale pour aller directement au contenu. Obligatoire pour tout site avec une navigation répétitive.

    <!-- En PREMIER dans le body -->
    <a href="#contenu-principal" class="skip-link">
      Aller au contenu principal
    </a>
    <!-- CSS -->
    .skip-link {
      position: absolute;
      top: -100px;           /* Hors écran par défaut */
      left: 16px;
      z-index: 9999;
      background: #1a1a2e;
      color: #fff;
      padding: 10px 18px;
      text-decoration: none;
      transition: top .2s;
    }
    .skip-link:focus {
      top: 0;                /* Visible au focus */
    }
    Pattern : Bouton icône accessible WCAG 4.1.2 — A

    Un bouton avec seulement une icône doit avoir un nom accessible. Sans texte visible, les lecteurs d'écran ne savent pas à quoi il sert.

    <!-- ❌ MAUVAIS : aucun nom accessible -->
    <button type="button">✕</button>
    <!-- ✅ CORRECT : aria-label donne le nom -->
    <button type="button" aria-label="Fermer la fenêtre">
      <span aria-hidden="true">✕</span>
    </button>
    <!-- ✅ AUSSI CORRECT : texte masqué visuellement -->
    <button type="button">
      <svg aria-hidden="true" focusable="false">...</svg>
      <span class="visually-hidden">Fermer la fenêtre</span>
    </button>
    <!-- CSS visually-hidden (meilleure pratique) -->
    .visually-hidden {
      position: absolute;
      width: 1px; height: 1px;
      overflow: hidden;
      clip: rect(0,0,0,0);
      white-space: nowrap;
    }
    Rendu

    ❌ Sans aria-label

    ✅ Avec aria-label

    Pattern : Bouton bascule (Toggle) WCAG 4.1.2 — A

    Un bouton qui s'active/désactive doit communiquer son état via aria-pressed. Le CSS cible cet attribut directement.

    <button type="button"
            aria-pressed="false"
            id="btn-theme">
      Mode sombre
    </button>
    /* CSS : cibler l'état ARIA directement */
    [aria-pressed="true"] {
      background: #1a1a2e;
      color: white;
    }
    var btn = document.getElementById('btn-theme');
    btn.addEventListener('click', function() {
      var etat = this.getAttribute('aria-pressed') === 'true';
      this.setAttribute('aria-pressed', String(!etat));
      this.setAttribute('aria-label',
        !etat ? 'Désactiver le mode sombre'
               : 'Activer le mode sombre');
    });
    Rendu interactif
    Pattern : Menu burger accessible WCAG 2.1.1 + 4.1.2

    Le bouton burger contrôle la visibilité du menu. aria-expanded + aria-controls communiquent l'état et la relation aux technologies d'assistance.

    <button type="button"
            id="burger"
            aria-controls="main-nav"
            aria-expanded="false"
            aria-label="Ouvrir le menu de navigation">
      <span aria-hidden="true">☰</span>
    </button>
    <nav id="main-nav" hidden>
      <!-- liens -->
    </nav>
    var burger = document.getElementById('burger');
    var nav = document.getElementById('main-nav');
    burger.addEventListener('click', function() {
      var ouvert = this.getAttribute('aria-expanded') === 'true';
      this.setAttribute('aria-expanded', String(!ouvert));
      this.setAttribute('aria-label',
        ouvert ? 'Ouvrir le menu' : 'Fermer le menu');
      if (ouvert) {
        nav.setAttribute('hidden', '');
      } else {
        nav.removeAttribute('hidden');
      }
    });
    Pattern : Validation de formulaire accessible WCAG 3.3.1 + 3.3.3 — A/AA

    Les messages d'erreur doivent être annoncés par les lecteurs d'écran et liés aux champs en erreur via aria-describedby + aria-invalid.

    <!-- Champ valide -->
    <div>
      <label for="email">
        Email <span aria-hidden="true">*</span>
        <span class="visually-hidden">(obligatoire)</span>
      </label>
      <input type="email"
             id="email"
             name="email"
             required
             aria-required="true"
             aria-describedby="email-aide email-erreur"
             aria-invalid="false">
      <small id="email-aide">Format : vous@exemple.com</small>
      <span id="email-erreur"
            role="alert"
            aria-live="assertive"
            hidden>
        ❌ Email invalide. Vérifiez le format.
      </span>
    </div>
    function afficherErreur(inputId, msgId) {
      var input = document.getElementById(inputId);
      var msg = document.getElementById(msgId);
      input.setAttribute('aria-invalid', 'true');
      msg.removeAttribute('hidden');
    }
    function effacerErreur(inputId, msgId) {
      var input = document.getElementById(inputId);
      var msg = document.getElementById(msgId);
      input.setAttribute('aria-invalid', 'false');
      msg.setAttribute('hidden', '');
    }
    Rendu interactif
    Format attendu : [email protected]
    Pattern : Modale accessible (Focus Trap) WCAG 2.1.2 + 2.4.3 — A

    Une modale accessible doit : piéger le focus à l'intérieur (focus trap), se fermer avec Échap, remettre le focus sur l'élément déclencheur à la fermeture, et bloquer la navigation dans le reste de la page.

    <button id="open-modal" type="button"
            aria-haspopup="dialog">
      Ouvrir la modale
    </button>
    <div id="modale"
         role="dialog"
         aria-modal="true"
         aria-labelledby="modal-titre"
         aria-describedby="modal-desc"
         hidden>
      <div class="modal-box">
        <h2 id="modal-titre">Titre de la modale</h2>
        <p id="modal-desc">Description du contenu.</p>
        <button id="close-modal" type="button"
                aria-label="Fermer la modale">✕</button>
      </div>
    </div>
    var trigger, modal, closeBtn;
    function ouvrir() {
      trigger = document.activeElement;
      modal.removeAttribute('hidden');
      document.body.style.overflow = 'hidden';
      closeBtn.focus();
      document.addEventListener('keydown', trapFocus);
    }
    function fermer() {
      modal.setAttribute('hidden', '');
      document.body.style.overflow = '';
      document.removeEventListener('keydown', trapFocus);
      trigger.focus();
    }
    function trapFocus(e) {
      if (e.key === 'Escape') { fermer(); return; }
      if (e.key !== 'Tab') return;
      var focusables = modal.querySelectorAll(
        'a[href], button, input, [tabindex]:not([tabindex="-1"])'
      );
      var first = focusables[0];
      var last  = focusables[focusables.length - 1];
      if (e.shiftKey && document.activeElement === first) {
        e.preventDefault();
        last.focus();
      } else if (!e.shiftKey && document.activeElement === last) {
        e.preventDefault();
        first.focus();
      }
    }
    Pattern : Live Region (zone de mise à jour) WCAG 4.1.3 — AA

    Les contenus qui se mettent à jour dynamiquement (notifications, résultats de recherche, messages de statut) doivent être annoncés par les lecteurs d'écran sans que le focus soit déplacé.

    <!-- role="alert" : annonce immédiate (assertive) -->
    <div role="alert" aria-live="assertive" aria-atomic="true">
      <!-- Vide au départ, rempli par JS en cas d'erreur critique -->
    </div>
    <!-- role="status" : annonce différée (polite) -->
    <div role="status" aria-live="polite" aria-atomic="true">
      <!-- Confirmations, informations, résultats -->
    </div>
    <!-- Exemple : notification de succès -->
    <div id="notif"
         aria-live="polite"
         aria-atomic="true"
         class="visually-hidden">
    </div>
    function notifier(message) {
      var zone = document.getElementById('notif');
      zone.textContent = '';           // Vider d'abord
      setTimeout(function() {
        zone.textContent = message;
      }, 100);
    }
    Rendu interactif (vérifier avec un lecteur d'écran)
    Zone de notification (vide)
    Pattern : Onglets accessibles (Tabs) WCAG 2.1.1 + 4.1.2

    Le pattern tabs utilise role="tablist", role="tab", role="tabpanel" et les flèches clavier pour naviguer entre onglets.

    <div role="tablist" aria-label="Onglets de cours">
      <button role="tab"
              id="tab-html"
              aria-controls="panel-html"
              aria-selected="true"
              tabindex="0">HTML</button>
      <button role="tab"
              id="tab-css"
              aria-controls="panel-css"
              aria-selected="false"
              tabindex="-1">CSS</button>
    </div>
    <div role="tabpanel"
         id="panel-html"
         aria-labelledby="tab-html">
      Contenu du panel HTML
    </div>
    <div role="tabpanel"
         id="panel-css"
         aria-labelledby="tab-css"
         hidden>
      Contenu du panel CSS
    </div>
    <!-- Navigation clavier : flèche gauche/droite entre tabs
         tabindex="-1" sur les tabs non sélectionnés
         tabindex="0" sur le tab actif -->
    Rendu interactif (flèches ← → pour naviguer)
    HTML — HyperText Markup Language. La structure de la page.
    Pattern : Contraste des couleurs WCAG 1.4.3 + 1.4.11 — AA

    Le ratio de contraste est calculé entre la couleur du texte et son arrière-plan.

    ✅ PASSE — 16.1:1 (AAA)

    #1a1a2e sur #ffffff

    ✅ PASSE — 5.1:1 (AA)

    #b91c1c sur #ffffff

    ✅ PASSE — 4.6:1 (AA)

    #b45309 sur #ffffff

    ❌ ÉCHOUE — 2.5:1 (insuffisant)

    #22c55e sur #ffffff — contraste 2.28:1 (insuffisant)

    ❌ ÉCHOUE — 2.8:1 (insuffisant)

    #f59e0b sur #ffffff — contraste 2.15:1 (insuffisant)

    ✅ PASSE — 5.2:1 (AA en dark)

    #22c55e sur #1c1c30

    Outils de vérification : WebAIM Contrast Checker, Colour Contrast Analyser, extensions navigateur : axe, WAVE, Accessibility Insights.

    Pattern : Focus visible WCAG 2.4.7 — AA

    Tout élément interactif doit avoir un indicateur de focus visible pour les utilisateurs clavier. Utiliser :focus-visible (focus clavier uniquement, pas souris) plutôt que :focus.

    /* ❌ MAUVAIS — supprime tout focus */
    * { outline: none; }
    a:focus { outline: none; }
    /* ✅ CORRECT — focus clavier visible, souris invisible */
    :focus-visible {
      outline: 3px solid #005fcc;
      outline-offset: 3px;
      border-radius: 3px;
    }
    :focus:not(:focus-visible) {
      outline: none;   /* Retire l'outline pour les clics souris */
    }
    /* Focus personnalisé avec box-shadow (contourne les overflow:hidden) */
    :focus-visible {
      outline: none;
      box-shadow: 0 0 0 3px #fff, 0 0 0 5px #005fcc;
    }
    Rendu (Tab pour voir le focus)
    Lien (Tab me)
    Outils

    Outils de test et ressources

    Comment tester l'accessibilité Outils

    🔌 Extensions navigateur

    • axe DevTools — Le plus complet, gratuit
    • WAVE — Visualisation des erreurs
    • Accessibility Insights — Microsoft
    • Lighthouse — Intégré Chrome DevTools
    • Color Contrast Analyzer — TPGI

    📢 Lecteurs d'écran

    • NVDA — Windows, gratuit (le + utilisé)
    • JAWS — Windows, payant (professionnel)
    • VoiceOver — macOS/iOS, intégré
    • TalkBack — Android, intégré
    • Orca — Linux, gratuit

    🌐 Outils en ligne

    • validator.w3.org — Validation HTML
    • webaim.org/contrast — Contraste
    • accessibilityinsights.io — Audit
    • whocanuse.com — Simulation daltonisme
    • rgaa.numerique.gouv.fr — Référentiel RGAA

    ✅ Checklist rapide

    • Naviguer au clavier (Tab, Entrée, Échap)
    • Tester avec NVDA + Chrome
    • Zoomer à 200% et 400%
    • Tester en mode contraste élevé
    • Couper JavaScript et tester
    • Passer axe ou WAVE
    • Valider le HTML (W3C)