Leçon 2/7 10 min

HTML sémantique : 80 % du travail

Le bon élément natif donne gratuitement le rôle, le focus et le clavier. Landmarks, hiérarchie de titres : la structure que les lecteurs d'écran utilisent pour naviguer.

Le bouton qui n'en était pas un

Dans la leçon 1, Marie ne pouvait pas valider son panier. Le « bouton » de la page était un <div> avec un onclick. À la souris, ça marchait. Au clavier et au lecteur d'écran, ça n'existait pas.

Voici pourquoi, en détail. Un <div> est une boîte neutre. Il n'a aucun rôle : le lecteur d'écran ne l'annonce pas comme un bouton. Il n'est pas focusable : la touche Tab passe à côté. Il n'a aucun comportement clavier : Entrée et Espace ne déclenchent rien. Un onclick ne réagit qu'à la souris.

Le <button> natif, lui, donne tout ça gratuitement. Tu écris une balise, et le navigateur t'offre le rôle, le focus, le clavier et l'état désactivé. Sans une ligne de JavaScript en plus.

Ce que tu obtiens<div onclick><button>
Rôle annoncé (« bouton »)❌ aucun✅ natif
Focusable au clavier (Tab)❌ non✅ oui
Activation Entrée❌ non✅ oui
Activation Espace❌ non✅ oui
État désactivé (disabled)❌ à coder✅ natif

Cinq cadeaux, une seule balise. Reconstruire tout ça à la main sur un <div> prend des dizaines de lignes, et tu en oublieras toujours une. Le natif ne se trompe jamais.

La règle qui résume 80 % de l'accessibilité

L'élément natif d'abord. Avant d'inventer un composant, demande-toi quelle balise HTML fait déjà le travail. Un bouton, c'est <button>. Un lien, c'est <a href>. Une case à cocher, c'est <input type="checkbox">. Le natif arrive avec son rôle, son focus et son clavier intégrés. Tu ne les recodes pas, tu les hérites.

Reste un piège classique : confondre bouton et lien. Visuellement, on peut les rendre identiques. Pour l'accessibilité, ce sont deux choses différentes.

  • Un lien (<a href>) navigue. Il emmène l'utilisateur ailleurs : une autre page, une autre section. Le lecteur d'écran l'annonce « lien », et l'utilisateur sait qu'il va se déplacer.
  • Un bouton (<button>) agit. Il déclenche une action sur place : valider, ouvrir un menu, ajouter au panier. Le lecteur d'écran l'annonce « bouton », et l'utilisateur sait que quelque chose va se passer ici.

Le lecteur d'écran les annonce différemment, et l'utilisateur en attend des comportements différents. Un lien qui agit, ou un bouton qui navigue, c'est une promesse trahie. « Valider le panier » est une action : c'est un bouton. « Voir mes commandes » est une navigation : c'est un lien.

Les landmarks : le GPS du lecteur d'écran

Tu connais déjà <header>, <nav>, <main>, <footer> côté structure. On les revisite ici par l'angle accessibilité. Ces balises créent des landmarks : des repères dans l'arbre d'accessibilité.

Pourquoi ça compte ? Un voyant lit la page de haut en bas, mais saute des yeux ce qui ne l'intéresse pas. Un utilisateur de lecteur d'écran ne voit rien : il navigue par landmarks et par titres. C'est son Ctrl+F. Il appuie sur une touche et saute directement à la navigation, ou au contenu principal, ou au pied de page.

  • <header> : l'en-tête de la page (logo, titre du site).
  • <nav> : un bloc de navigation. Annoncé « navigation ».
  • <main> : le contenu principal, unique sur la page.
  • <aside> : un contenu de côté (encart, liens connexes).
  • <footer> : le pied de page.

Une page sans <main> n'a pas de raccourci « aller au contenu ». Le lecteur d'écran propose un saut direct vers le contenu principal, à condition qu'un <main> existe. Sans lui, l'utilisateur doit re-traverser tout l'en-tête et le menu à chaque page. Sur un site de dix pages, c'est dix fois le même menu réécouté avant d'arriver au vrai contenu.

Les titres : le sommaire que personne ne voit

L'autre grand outil de navigation, c'est la liste des titres. Le lecteur d'écran peut afficher tous les <h1> à <h6> d'une page comme un sommaire, et l'utilisateur saute de l'un à l'autre. Cette liste est le plan de ta page.

Deux règles simples gardent ce plan lisible.

  • Un seul <h1> par page : le titre du contenu, le sommet du plan.
  • Pas de saut de niveau. Après un <h2> vient un <h3>, pas un <h4>. Sauter de <h2> à <h4> laisse un trou dans le plan : l'utilisateur se demande quelle section il a ratée.

Le piège : beaucoup de gens choisissent un niveau de titre pour sa taille. « Je veux du petit, je mets <h4>. » Non. Le niveau dit la place dans la hiérarchie, pas la taille. La taille, c'est le CSS. Choisis le bon niveau, puis stylise-le.

Prédis avant de lire

Le labo ci-dessous contient une mini-page truffée de problèmes d'accessibilité, mais qui s'affiche très bien à l'écran. Combien de problèmes vas-tu trouver ? Cherche d'abord, puis compare.

Voir la réponse

Il y en a 5, et aucun ne se voit à l'œil. Un faux bouton en <div>, une navigation en <div>, l'absence de <main>, un saut de titre <h1> vers <h3>, et un faux lien en <span>. Le rendu est parfait ; l'arbre d'accessibilité, lui, est cassé. C'est tout le piège de l'accessibilité : ce qui manque ne se voit pas. Ouvre le détail complet sous le labo après avoir cherché.

Ce que le lecteur d'écran « voit »

À gauche, la page découpée en landmarks. À droite, la liste des titres comme un sommaire. Ce sont les deux cartes que le lecteur d'écran utilise pour se déplacer, sans jamais voir un seul pixel.

À gauche, une page web découpée en landmarks empilés et étiquetés : header, nav, main (le plus grand), aside, footer. À droite, la liste des titres comme un sommaire : h1 Mon panier, puis h2 Articles, h2 Livraison, et sous Livraison un h3 Adresse. Une accolade relie les deux : ce sont les deux cartes de navigation du lecteur d'écran. Landmarks de la page header nav main le contenu principal, unique aside footer Sommaire des titres h1  Mon panier h2  Articles h2  Livraison h3  Adresse Pas de saut : h1 → h2 → h3, jamais h1 → h3.
Deux cartes invisibles : les landmarks et la liste des titres. Le lecteur d'écran saute de l'une à l'autre.

À toi : trouve et corrige les 5 problèmes

Voici une mini-page de boutique. Elle s'affiche parfaitement, mais elle cache 5 problèmes d'accessibilité. Édite le code à gauche, corrige-les avec ce que tu viens d'apprendre, et clique sur Exécuter pour voir le rendu. Le visuel ne changera presque pas : c'est normal, l'accessibilité se joue dans la structure, pas dans les pixels.

Corrige les 5 problèmes
Voir les 5 problèmes et les corrections
  1. Navigation en <div class="nav"> → remplace par <nav>. Le lecteur d'écran l'annoncera comme un landmark « navigation », et l'utilisateur pourra y sauter directement.
  2. Pas de <main> → enveloppe le contenu principal (titre, produit, bouton) dans <main>. Sans lui, pas de raccourci « aller au contenu ».
  3. Saut de titre <h1><h3> → le nom du modèle doit être un <h2>. Le niveau dit la place dans le plan, pas la taille.
  4. Faux bouton <div class="btn" onclick><button onclick="acheter()">Ajouter au panier</button>. Rôle, focus et clavier deviennent natifs.
  5. Faux lien <span class="link" onclick> → « Voir les conditions de vente » est une navigation : <a href="/cgv">. Un vrai lien, focusable et activable au clavier.

Le code corrigé :

<nav>
    <a href="#">Accueil</a>
    <a href="#">Boutique</a>
</nav>

<main>
    <h1>Chaussures de course</h1>

    <h2>Modèle Sprint 200</h2>
    <p>Légère, respirante, idéale route.</p>

    <button onclick="acheter()">Ajouter au panier</button>

    <p>
        <a href="/cgv">Voir les conditions de vente</a>
    </p>
</main>

The button that wasn't one

In lesson 1, Marie couldn't check out her cart. The page's "button" was a <div> with an onclick. With a mouse, it worked. For the keyboard and the screen reader, it didn't exist.

Here's why, in detail. A <div> is a neutral box. It has no role: the screen reader doesn't announce it as a button. It is not focusable: the Tab key skips right past it. It has no keyboard behaviour: Enter and Space trigger nothing. An onclick only reacts to the mouse.

The native <button>, on the other hand, gives all of that for free. You write one tag, and the browser hands you the role, the focus, the keyboard and the disabled state. Without a single extra line of JavaScript.

What you get<div onclick><button>
Announced role ("button")❌ none✅ native
Keyboard-focusable (Tab)❌ no✅ yes
Enter activation❌ no✅ yes
Space activation❌ no✅ yes
Disabled state (disabled)❌ to code✅ native

Five gifts, one tag. Rebuilding all of that by hand on a <div> takes dozens of lines, and you'll always forget one. The native element never gets it wrong.

The rule that sums up 80% of accessibility

Native element first. Before inventing a component, ask which HTML tag already does the job. A button is <button>. A link is <a href>. A checkbox is <input type="checkbox">. The native element arrives with its role, focus and keyboard built in. You don't recode them, you inherit them.

One classic trap remains: confusing a button with a link. Visually, you can make them identical. For accessibility, they are two different things.

  • A link (<a href>) navigates. It takes the user elsewhere: another page, another section. The screen reader announces it as "link", and the user knows they're about to move.
  • A button (<button>) acts. It triggers an action right here: submit, open a menu, add to cart. The screen reader announces it as "button", and the user knows something is about to happen on this spot.

The screen reader announces them differently, and the user expects different behaviours. A link that acts, or a button that navigates, is a broken promise. "Check out the cart" is an action: it's a button. "View my orders" is navigation: it's a link.

Landmarks: the screen reader's GPS

You already know <header>, <nav>, <main>, <footer> from the structure angle. We revisit them here through the accessibility lens. These tags create landmarks: reference points in the accessibility tree.

Why does it matter? A sighted person reads the page top to bottom but skips with their eyes whatever doesn't interest them. A screen reader user sees nothing: they navigate by landmarks and headings. It's their Ctrl+F. They press a key and jump straight to the navigation, or the main content, or the footer.

  • <header>: the page header (logo, site title).
  • <nav>: a navigation block. Announced as "navigation".
  • <main>: the main content, unique on the page.
  • <aside>: side content (callout, related links).
  • <footer>: the page footer.

A page with no <main> has no "skip to content" shortcut. The screen reader offers a direct jump to the main content, provided a <main> exists. Without it, the user has to wade back through the whole header and menu on every page. On a ten-page site, that's the same menu heard ten times before reaching the real content.

Headings: the table of contents nobody sees

The other big navigation tool is the heading list. The screen reader can show every <h1> to <h6> on a page as a table of contents, and the user jumps from one to the next. That list is your page's outline.

Two simple rules keep that outline readable.

  • One single <h1> per page: the content's title, the top of the outline.
  • No level skipping. After an <h2> comes an <h3>, not an <h4>. Jumping from <h2> to <h4> leaves a hole in the outline: the user wonders which section they missed.

The trap: many people pick a heading level for its size. "I want it small, I'll use <h4>." No. The level says the place in the hierarchy, not the size. Size is CSS. Pick the right level, then style it.

Predict before reading on

The lab below holds a mini-page riddled with accessibility problems, yet it displays perfectly on screen. How many problems will you find? Look first, then compare.

Show the answer

There are 5, and none of them are visible to the eye. A fake button in a <div>, a navigation in a <div>, the missing <main>, a heading jump from <h1> to <h3>, and a fake link in a <span>. The rendering is perfect; the accessibility tree is broken. That's the whole trap of accessibility: what's missing doesn't show. Open the full breakdown under the lab once you've searched.

What the screen reader "sees"

On the left, the page split into landmarks. On the right, the heading list as a table of contents. These are the two maps the screen reader uses to move around, without ever seeing a single pixel.

On the left, a web page split into stacked, labelled landmarks: header, nav, main (the largest), aside, footer. On the right, the heading list as a table of contents: h1 My cart, then h2 Items, h2 Delivery, and under Delivery an h3 Address. A brace links the two: these are the screen reader's two navigation maps. Page landmarks header nav main the main content, unique aside footer Heading outline h1  My cart h2  Items h2  Delivery h3  Address No skip: h1 → h2 → h3, never h1 → h3.
Two invisible maps: the landmarks and the heading list. The screen reader jumps from one to the other.

Your turn: find and fix the 5 problems

Here's a mini shop page. It displays perfectly, but it hides 5 accessibility problems. Edit the code on the left, fix them with what you just learned, and click Run to see the result. The visuals will barely change: that's expected, accessibility plays out in the structure, not in the pixels.

Fix the 5 problems
Show the 5 problems and the fixes
  1. Navigation in <div class="nav"> → replace with <nav>. The screen reader will announce it as a "navigation" landmark, and the user can jump straight to it.
  2. No <main> → wrap the main content (title, product, button) in <main>. Without it, no "skip to content" shortcut.
  3. Heading jump <h1><h3> → the model name should be an <h2>. The level says the place in the outline, not the size.
  4. Fake button <div class="btn" onclick><button onclick="buy()">Add to cart</button>. Role, focus and keyboard become native.
  5. Fake link <span class="link" onclick> → "See terms of sale" is navigation: <a href="/terms">. A real link, focusable and keyboard-activable.

The fixed code:

<nav>
    <a href="#">Home</a>
    <a href="#">Shop</a>
</nav>

<main>
    <h1>Running shoes</h1>

    <h2>Sprint 200 model</h2>
    <p>Light, breathable, ideal for the road.</p>

    <button onclick="buy()">Add to cart</button>

    <p>
        <a href="/terms">See terms of sale</a>
    </p>
</main>

🎯 Pratique

S'entraîner (clique pour ouvrir) :

💬 Ré-explique sans regarder
Ré-explique sans regarder

Explique à un collègue pourquoi un <button> est meilleur qu'un <div onclick> pour l'accessibilité. Cite au moins trois choses que le natif donne gratuitement.

Une bonne explication dit : un <div> est une boîte neutre, sans rôle, non focusable, sans clavier. Le <button> natif donne gratuitement (1) le rôle « bouton » annoncé par le lecteur d'écran, (2) le focus au clavier via Tab, (3) l'activation par Entrée ET Espace, (4) l'état désactivé. La règle d'or : l'élément natif d'abord, on hérite au lieu de recoder.
🧠 Rappel libre
Rappel libre

Sans remonter : par quoi un utilisateur de lecteur d'écran navigue-t-il dans une page, et que perd-il si la page n'a pas de <main> ?

Il navigue par landmarks (header, nav, main, aside, footer) et par liste de titres (h1 à h6) : c'est son Ctrl+F, il saute directement à la zone voulue. Sans <main>, il perd le raccourci « aller au contenu » et doit re-traverser tout l'en-tête et le menu à chaque page.
⚖️ Juge le code de l'IA
Accepter ou rejeter le code de l'IA

Tu demandes à l'IA une carte produit cliquable. Elle livre : <div class="card" onclick="ouvrir()">…</div> et commente : « J'ai pris un <div>, c'est plus flexible pour le style qu'un <button>. » Tu acceptes, ou tu rejettes ?

À rejeter. L'argument « plus flexible pour le style » est faux et dangereux : un <button> se stylise entièrement en CSS (un reset de quelques lignes suffit). En choisissant un <div onclick>, l'IA sacrifie le rôle, le focus et le clavier natifs : la carte devient invisible au lecteur d'écran et inutilisable sans souris. Le bon code : <button> (ou <a href> si la carte navigue vers une page produit). Le style n'est jamais une raison d'abandonner le natif.
Tu dois rendre cliquable une zone qui ouvre un menu. Quel élément choisis-tu en premier réflexe ?
« Retour à l'accueil » emmène l'utilisateur sur une autre page. Bouton ou lien ?
Tu veux un sous-titre plus petit, alors tu passes directement de <h2> à <h4>. Quel est le problème ?
Un dev ajoute un écouteur keydown sur Entrée à son faux bouton <div>. Au test, Entrée fonctionne, mais Espace ne fait toujours rien. Pourquoi ?
Prochaine étape

Le natif te donne le clavier gratuitement. Mais encore faut-il VOIR où on est. Leçon 3 : Tab, le focus visible, et le test de 30 secondes que presque personne ne fait.

Leçon 3 : Clavier et focus visible →

Une erreur dans cette leçon, un passage flou, une question ? Écrivez-moi : chaque retour améliore ce cours.

Besoin d'un développeur pour votre projet ?

Réponse sous 24h · Sans engagement