Le catalogue des plugins d’onglets pour WordPress est immense, mais leur qualité d’accessibilité est rarement au rendez-vous : beaucoup reposent sur des <div> cliquables sans gestion de touche, ou sur des bibliothèques JavaScript figées qui ne suivent pas le motif ARIA officiel. Pour un client qui souhaitait des onglets sur une page de présentation de services, nous avons choisi de construire un bloc personnalisé plutôt que d’installer une dépendance supplémentaire — moins de code tiers à maintenir, et un contrôle total sur l’accessibilité du résultat.
Le bloc s’enregistre comme n’importe quel bloc personnalisé, via register_block_type() côté PHP et un script d’édition en JavaScript. C’est le rendu final en façade — la partie visible par les visiteurs du site, générée par la fonction de rendu du bloc — qui nous intéresse ici, puisque c’est elle qui doit respecter le motif ARIA tabs.
La structure HTML du motif tabs
Le motif ARIA officiel distingue trois rôles : tablist pour le conteneur des boutons d’onglets, tab pour chaque bouton, et tabpanel pour chaque panneau de contenu associé :
<div class="onglets-services">
<div role="tablist" aria-label="Nos services">
<button role="tab" id="tab-conseil" aria-selected="true" aria-controls="panel-conseil">Conseil</button>
<button role="tab" id="tab-dev" aria-selected="false" aria-controls="panel-dev" tabindex="-1">Développement</button>
<button role="tab" id="tab-maintenance" aria-selected="false" aria-controls="panel-maintenance" tabindex="-1">Maintenance</button>
</div>
<div role="tabpanel" id="panel-conseil" aria-labelledby="tab-conseil">
<p>Contenu de l'onglet Conseil…</p>
</div>
<div role="tabpanel" id="panel-dev" aria-labelledby="tab-dev" hidden>
<p>Contenu de l'onglet Développement…</p>
</div>
<div role="tabpanel" id="panel-maintenance" aria-labelledby="tab-maintenance" hidden>
<p>Contenu de l'onglet Maintenance…</p>
</div>
</div>
Le détail qui change tout : un seul tab dans l’ordre de tabulation

Remarquez que seul le premier bouton d’onglet (celui sélectionné) porte un tabindex implicite normal, tandis que les autres reçoivent tabindex="-1". C’est volontaire, et c’est la partie la plus souvent ratée dans les implémentations maison : un appui sur Tab ne doit faire circuler l’utilisateur qu’entre un onglet actif et l’élément suivant de la page, jamais à travers chaque bouton d’onglet un par un. Le déplacement entre onglets se fait uniquement avec les flèches gauche et droite, une fois le focus posé sur le groupe.
Le script de navigation par flèches
document.querySelectorAll('[role="tablist"]').forEach((liste) => {
const onglets = Array.from(liste.querySelectorAll('[role="tab"]'));
onglets.forEach((onglet, index) => {
onglet.addEventListener('click', () => activerOnglet(onglets, onglet));
onglet.addEventListener('keydown', (event) => {
if (event.key === 'ArrowRight') {
activerOnglet(onglets, onglets[index + 1] || onglets[0]);
}
if (event.key === 'ArrowLeft') {
activerOnglet(onglets, onglets[index - 1] || onglets[onglets.length - 1]);
}
});
});
});
function activerOnglet(onglets, cible) {
onglets.forEach((onglet) => {
const actif = onglet === cible;
onglet.setAttribute('aria-selected', String(actif));
onglet.setAttribute('tabindex', actif ? '0' : '-1');
document.getElementById(onglet.getAttribute('aria-controls')).hidden = !actif;
});
cible.focus();
}
Enregistrer le bloc côté PHP
La fonction de rendu du bloc génère exactement ce HTML à partir des attributs saisis par l’utilisateur dans l’éditeur (titres d’onglets et contenu de chaque panneau, stockés comme un tableau d’objets dans les attributs du bloc) :
register_block_type( __DIR__ . '/build', array(
'render_callback' => 'agence_rendu_bloc_onglets',
) );
Ce que ce choix a évité
- Une dépendance supplémentaire à maintenir et à tenir à jour à chaque montée de version de WordPress.
- Un risque de conflit CSS avec un plugin d’onglets tiers qui charge sa propre feuille de style non maîtrisée.
- Une accessibilité incertaine, la plupart des plugins d’onglets grand public n’appliquant pas rigoureusement le motif ARIA complet.
Pour aller plus loin
Le motif complet, avec ses variantes d’orientation verticale et horizontale, est décrit dans le ARIA Authoring Practices Guide du W3C — la référence à suivre au pied de la lettre avant d’écrire tout composant à onglets, plugin ou bloc personnalisé.