Le WordPress d'aujourd'hui, décodé pour les développeurs

Accessibilité

Antipatterns de bouton fantôme : un div cliquable sans rôle ni focus

Un simple élément div, stylé comme un bouton et cliquable en JavaScript, reste invisible pour le clavier et les lecteurs d'écran. Pourquoi le remplacer par un vrai bouton HTML règle tout.

Par WordPress Développement • 3 octobre 2023 • 4 min de lecture • Aucun commentaire
Antipatterns de bouton fantôme : un div cliquable sans rôle ni focus

Un rectangle stylé en CSS avec une couleur de fond, une ombre portée légère, un curseur en forme de main au survol, et un gestionnaire d’évènement click en JavaScript : voilà à quoi ressemble le bouton fantôme le plus fréquent, observé sur de nombreux sites construits vite, souvent sous la pression d’un délai de livraison serré. Visuellement indiscernable d’un vrai bouton, ce motif de conception échoue pourtant sur trois points fondamentaux dès qu’on retire la souris.

Ce qu’on observe dans le code

Le code typique de ce bouton fantôme ressemble à ceci :

<div class="bouton-cta" onclick="validerFormulaire()">
  Envoyer ma demande
</div>

Rien dans cette ligne n’indique à une technologie d’assistance qu’il s’agit d’un élément interactif. Un <div> n’a, par défaut, aucun rôle sémantique particulier : un lecteur d’écran le traite comme un simple conteneur de texte, sans annoncer ni bouton ni action possible.

Pourquoi c’est un problème, précisément

L'essentiel à retenir : Un div n'obtient jamais le focus ni de rôle par défaut ; Trois attributs à ajouter manuellement pour compenser ; Remplacer par un bouton natif évite chaque compensation

Trois défauts s’accumulent sur ce type d’élément, chacun capable à lui seul de rendre l’action inaccessible :

  • Aucun rôle sémantique : un lecteur d’écran ne l’annonce jamais comme « bouton », l’utilisateur ignore qu’une action est disponible à cet endroit ;
  • Aucun focus au clavier : un <div> n’apparaît pas dans l’ordre de tabulation par défaut, impossible donc de l’atteindre sans souris ni écran tactile ;
  • Aucune activation au clavier : même en forçant le focus, l’évènement click attaché en JavaScript ne se déclenche pas automatiquement avec les touches Entrée ou Espace, contrairement à un bouton natif.

La compensation partielle, et ses limites

Il est possible de corriger ces trois défauts un par un, en ajoutant manuellement les attributs correspondants :

<div class="bouton-cta"
     role="button"
     tabindex="0"
     onclick="validerFormulaire()"
     onkeydown="if (event.key === 'Enter' || event.key === ' ') validerFormulaire()">
  Envoyer ma demande
</div>

Cette version corrigée fonctionne, mais elle demande quatre ajouts distincts (role, tabindex, gestion de Entrée, gestion d’Espace) pour reproduire un comportement qu’un élément natif offre sans aucune configuration. Elle oublie en général aussi un détail plus subtil : la touche Espace doit empêcher le défilement de la page par défaut, avec event.preventDefault(), une nuance presque systématiquement absente des corrections artisanales de ce type.

La correction qui règle tout d’un coup

<button type="button" class="bouton-cta" onclick="validerFormulaire()">
  Envoyer ma demande
</button>

Un élément <button> natif possède, sans aucune configuration supplémentaire : le rôle button annoncé automatiquement, sa place native dans l’ordre de tabulation, l’activation par Entrée et par Espace, et même l’état désactivé géré nativement via l’attribut disabled, sans qu’aucune ligne de JavaScript supplémentaire ne soit nécessaire. Le style visuel, lui, reste entièrement personnalisable en CSS, un bouton natif ne dictant aucune apparence imposée.

.bouton-cta {
    background: #0b4f8a;
    color: #fff;
    padding: 12px 24px;
    border: none;
    border-radius: 6px;
    font: inherit;
    cursor: pointer;
}

Un raccourci de vérification rapide

Un test suffit à repérer ce défaut sur un site existant : parcourir la page uniquement au clavier avec la touche Tab et observer si tous les éléments qui déclenchent une action visible reçoivent bien le focus, avec un contour identifiable. Tout élément cliquable qui n’apparaît jamais dans ce parcours est, presque systématiquement, un bouton fantôme construit sur un <div> ou un <span>.

La question à se poser avant d’écrire un gestionnaire de clic n’est jamais « quel élément stylé le mieux », mais « quel élément HTML porte déjà nativement le comportement attendu ».

En résumé

Le bouton fantôme reste l’un des antipatterns les plus simples à corriger, précisément parce que la solution ne demande aucun ajout : elle demande de retirer un mauvais choix d’élément HTML pour le remplacer par celui prévu depuis toujours pour cet usage. Un <button> natif règle en une ligne ce que quatre attributs ARIA et deux gestionnaires d’évènement tentent, souvent imparfaitement, de reproduire.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi