Niveau de titre dans un composant réutilisable : RGAA 9.1
En Bref : L'essentiel à retenir
- Le bon niveau d'un titre dépend de la page, pas du composant : un même
<Card>peut être h2 ici et h3 ailleurs. - L'algorithme d'outline HTML5 (h1 partout dans des
<section>) n'a jamais été implémenté par les navigateurs ni les lecteurs d'écran : ne comptez pas dessus. - L'attribut
headingoffsetexiste mais reste expérimental (Firefox Nightly derrière un drapeau) : inutilisable pour viser la conformité RGAA aujourd'hui. - La réponse fiable en production : passer le niveau en paramètre au composant et décider intentionnellement, pas déléguer à un algorithme.
- Un scan signale les sauts de niveau, mais le RGAA 4.1 ne les sanctionne pas : ce qui se juge au critère 9.1, c'est la cohérence de la hiérarchie et la pertinence des titres, un travail humain.
Vous construisez un design system. Votre composant <Card> affiche un titre. Sur la page d'accueil, il vient après un <h1> et devrait être un <h2>. Dans une grille imbriquée d'une page interne, il devrait être un <h3>. Quel niveau coder dans le composant ? La mauvaise réponse, répandue, consiste à espérer qu'un mécanisme du navigateur tranche à votre place. La bonne réponse est plus simple et tient en une règle, doublée d'un paramètre.
Le principe : le niveau appartient à la page, pas au composant
Un titre n'a pas de niveau « en soi ». Son niveau exprime sa position dans la hiérarchie de la page qui l'accueille. Le même composant, réutilisé à deux profondeurs différentes, doit donc produire deux niveaux différents. C'est précisément ce que vérifie le critère RGAA 9.1 : l'information doit être structurée par des titres appropriés, dans une hiérarchie pertinente. Précision qui compte, car beaucoup de contenus disent encore le contraire : depuis le RGAA 4.1, un saut de niveau (un h2 suivi directement d'un h4) n'invalide plus le critère, tant que la hiérarchie reste cohérente. Il reste déconseillé. Ce critère s'appuie sur le critère WCAG 1.3.1 (Information et relations).
Le piège du composant réutilisable, c'est qu'il est écrit une fois et rendu dans plusieurs contextes. Coder un niveau en dur (<h3> figé dans la <Card>) garantit un saut de niveau dès que le contexte change. D'où la tentation de déléguer la décision à la plateforme. Deux fausses pistes circulent.
Fausse piste 1 : l'algorithme d'outline (qui n'existe pas)
La spécification HTML5 a un temps décrit un outline algorithm : en imbriquant des <section>, on pouvait théoriquement mettre des <h1> partout, et l'arbre de titres se recalculait tout seul selon la profondeur de sectionnement.
Le problème : aucun navigateur ni aucun lecteur d'écran ne l'a jamais implémenté, et la spécification a fini par l'abandonner. Un <h1> imbriqué dans trois <section> reste annoncé « titre de niveau 1 » par NVDA, JAWS ou VoiceOver. Mettre des h1 partout en croyant que la technologie ajustera produit donc une hiérarchie plate et fausse, en échec sur le critère 9.1.
Attention
« Utilisez des h1 partout, le sectionnement s'occupe du reste » est un conseil périmé. Le niveau réel d'un titre est celui de sa balise, point. Pour le vérifier sur une vraie page, notre validateur de structure de titres reconstitue l'arbre tel que le percevra un lecteur d'écran.
Fausse piste 2 : headingoffset, prometteur mais expérimental
Plus récemment, un attribut headingoffset a été proposé pour répondre exactement à ce besoin. Posé sur un conteneur, il décale d'autant le niveau des titres descendants : un <h1> dans un <section headingoffset="1"> est exposé comme un h2. Manuel Matuzović en détaille le fonctionnement dans Context-aware headings in HTML : on code tous les titres de composant en h1, et chaque conteneur parent applique son décalage, qui se cumule à l'imbrication.
Sur le papier, c'est élégant pour un design system. En pratique, deux limites le rendent inexploitable aujourd'hui pour viser la conformité :
- Support quasi nul : à ce jour,
headingoffsetn'est disponible qu'en Firefox Nightly, derrière un drapeau. Aucun navigateur stable, aucun lecteur d'écran grand public ne le gère. - Aucune automatisation réelle : comme le rappelle Adrian Roselli dans headingoffset is Not the Document Outline Algorithm, l'attribut exige toujours une décision humaine sur la valeur de décalage en fonction du contexte. Il ne devine rien. Le confondre avec un algorithme d'outline ressuscité mène à « de la confusion et du risque WCAG ».
headingoffset est une piste à suivre, pas une solution à déployer. Le noter dans une veille technique a du sens ; baser la conformité d'un site livré dessus, non.
La réponse fiable : passer le niveau en paramètre
La technique qui marche partout, aujourd'hui, sans drapeau ni pari sur le navigateur, c'est de rendre le niveau explicite et injecté. Le composant ne décide pas de son niveau : la page qui l'utilise le lui fournit.
// Le composant accepte le niveau, avec un défaut raisonnable
function Card({ level = 2, title, children }) {
const Heading = `h${level}`; // h2, h3, h4...
return (
<article className="card">
<Heading className="card__title">{title}</Heading>
{children}
</article>
);
}
// La page décide du niveau selon son contexte
<Card level={2} title="Entrée gratuite au musée" /> {/* sous le h1 */}
<Card level={3} title="Horaires" /> {/* dans une sous-section */}
Le même principe vaut en Web Components (un attribut level lu par le composant) ou côté CMS (un champ « niveau de titre » sur le bloc). L'idée centrale est la même : l'intention reste celle de l'auteur de la page, ce que le critère 9.1 attend, et elle ne dépend d'aucune fonctionnalité expérimentale. Pour les composants de design system, voir aussi notre guide concevoir un design system accessible et le cas spécifique des Web Components accessibles.
Reste un garde-fou : un niveau injectable peut être mal injecté. Documentez la règle, ajoutez un test qui échoue sur un saut de niveau, et vérifiez le rendu final. Dans les applications React ou Vue où le DOM se recompose, les sauts de niveau apparaissent souvent après coup : notre article sur le focus et la structure dans les SPA détaille ces pièges de rendu.
Tableau de décision : quel niveau pour quel contexte
| Situation | Approche | Statut RGAA 9.1 |
|---|---|---|
| Niveau codé en dur dans le composant | À éviter : saut de niveau dès que le contexte change | Échec probable |
h1 partout + sectionnement, en attente de l'outline | Fausse piste : algorithme jamais implémenté | Échec |
headingoffset sur les conteneurs | Expérimental (Firefox Nightly), non livrable | Non fiable aujourd'hui |
| Niveau passé en paramètre par la page | Recommandé : intention explicite, support universel | Conforme si la page est cohérente |
La ligne directrice : tout ce qui délègue la décision de niveau à un mécanisme automatique est, à ce jour, soit mort, soit expérimental. Tout ce qui garde la décision chez l'auteur de la page fonctionne.
Ce qu'un scan détecte, et ce qui reste humain
Soyons précis sur la frontière de l'automatisation. Un scan signale les sauts de niveau (un h2 suivi d'un h4), l'absence de h1 et les titres vides : ce sont des contrôles structurels déterministes, fiables et instantanés. Seul le titre vide constitue à lui seul une non-conformité ; les deux autres sont des signaux à examiner, puisque le RGAA 4.1 ne les sanctionne pas. C'est la partie du critère 9.1 qu'une machine couvre bien : repérer ce qui mérite un regard.
En revanche, juger qu'un texte mérite d'être un titre, et qu'il occupe le bon rang dans le sens de la page, demande de comprendre le contenu. Un <h2> syntaxiquement valide peut être au mauvais niveau logique sans qu'aucun calcul ne le signale. Cette évaluation reste manuelle, à l'image d'une large part du RGAA, dont une majorité de critères ne s'automatise pas entièrement. Un outil ne délivre donc jamais un verdict de conformité, et un bon score sur la structure des titres est un jalon, pas une déclaration légale.
Vu ainsi, l'automatisation débroussaille utilement. Un audit RGAA gratuit repère en quelques secondes les sauts de niveau et les titres manquants sur l'ensemble d'une page, ce qui vous laisse concentrer votre relecture sur ce qui compte vraiment : la cohérence de la hiérarchie et la pertinence de chaque titre dans son contexte. Commencez par repérer les ruptures, finissez par juger le sens.
Note
Les analyses techniques citées proviennent de billets publics de Manuel Matuzović et d'Adrian Roselli. Pour la formulation officielle du critère, reportez-vous aux critères et tests du RGAA 4.1.2 (avril 2023), socle français de l'EN 301 549 et de la directive européenne 2019/882 (European Accessibility Act), applicable depuis le 28 juin 2025.
Questions fréquentes
Quel critère RGAA encadre la hiérarchie des titres ?
Le critère 9.1, qui vérifie que l'information est structurée par des titres appropriés. Son test 9.1.1 porte sur la PERTINENCE de la hiérarchie, pas sur sa continuité : depuis le RGAA 4.1, le glossaire précise que « la présence de sauts hiérarchiques n'invalide pas le critère tant que cette hiérarchie plus lâche reste cohérente ». Sauter un niveau reste déconseillé, mais ne rend pas la page non conforme. Le critère s'appuie sur WCAG 1.3.1 (Information et relations).
Peut-on mettre des h1 partout et laisser le navigateur calculer le niveau ?
Non. C'était la promesse de l'algorithme d'outline défini dans HTML5, mais aucun navigateur ni lecteur d'écran ne l'a jamais implémenté, et la spécification l'a abandonné. Un h1 imbriqué dans des sections reste annoncé comme un h1. Le niveau réel est celui de la balise, pas celui qu'un algorithme déduirait.
L'attribut headingoffset règle-t-il le problème des composants ?
Pas encore en production. headingoffset décale le niveau des titres descendants, mais il n'est implémenté qu'en Firefox Nightly derrière un drapeau à ce jour. Il exige aussi une décision humaine sur la valeur de décalage : il n'automatise rien. Pour viser la conformité RGAA maintenant, passez le niveau en paramètre plutôt que de compter sur cet attribut.
Un scan automatique vérifie-t-il la hiérarchie des titres ?
Il repère de façon fiable les titres vides, les sauts de niveau et l'absence de h1, car ce sont des contrôles structurels. Mais attention à ce qu'il faut en conclure : ni le saut de niveau ni l'absence de h1 ne sont des non-conformités au RGAA 4.1, le glossaire l'admet explicitement. Ce sont des signaux à examiner. Juger qu'un texte mérite d'être un titre, et à quel niveau dans le sens de la page, demande une compréhension du contenu : cette part reste manuelle, comme une large part du RGAA.
Guides RGAA associés
Pour aller plus loin sur les sujets abordés dans cet article, consultez nos fiches techniques :
L'information doit être structurée par l'utilisation appropriée de titres (h1 à h6). La hiérarchie des titres doit être logique et ne pas sauter de niveaux.
Chaque image porteuse d'information doit avoir une alternative textuelle pertinente via l'attribut alt. Les images décoratives doivent avoir un attribut alt vide.
Chaque champ de formulaire doit avoir une étiquette (label) qui lui est liée explicitement.
Vidéos RGAA sur ce thème
Pour voir ces sujets en action, regardez les épisodes vidéo correspondants :
Articles similaires
Votre site est-il conforme ?
Ne prenez pas de risques avec l'accessibilité. Lancez un audit complet de votre site en quelques minutes et obtenez un rapport détaillé des corrections à apporter.