Essayez sans attendre l'hébergement proposé par WordPress
-15% sur le premier mois avec le code 2025PRESS15AFF

Essayer maintenant

Créer un thème WordPress FSE accessible (WCAG 2.2) avec theme.json : checklist complète 2026

L’accessibilité web, on en parle souvent… mais on l’applique vraiment beaucoup moins souvent. Avec l’arrivée des thèmes FSE (Full Site Editing) et les nouvelles exigences WCAG 2.2, la question n’est plus optionnelle : construire un thème WordPress accessible est devenu une compétence incontournable pour tout développeur sérieux. Dans cet article, on va voir concrètement comment utiliser theme.json pour poser des bases solides, et vous repartez avec une checklist complète pour valider votre conformité point par point.

Accessibilité WCAG 2.2 et Full Site Editing : ce que ça change vraiment

On va être directs : créer un thème WordPress accessible en 2026, c’est beaucoup plus complexe qu’il y a quelques années. Entre les nouveaux critères WCAG 2.2 publiés en octobre 2023 et l’arrivée du Full Site Editing, les règles du jeu ont clairement changé. Voici ce qu’il faut vraiment comprendre avant de se lancer.

Les nouveautés WCAG 2.2 à connaître absolument

WCAG 2.2 ne repart pas de zéro — il vient s’ajouter aux critères WCAG 2.1 existants. Mais certains ajouts sont particulièrement importants pour les développeurs de thèmes.

Le critère 2.4.11 – Focus Not Obscured (niveau AA) impose qu’un composant qui reçoit le focus clavier ne soit pas entièrement masqué par d’autres éléments (sticky headers, modales, etc.). Son pendant renforcé, le 2.4.12 (niveau AAA), va encore plus loin : aucune partie du focus ne doit être cachée.

Le critère 2.5.3 – Dragging Movements concerne les interactions qui requièrent un glisser-déposer : il faut toujours proposer une alternative accessible sans geste complexe. C’est particulièrement pertinent si votre thème intègre des sliders ou des composants de ce type.

Côté formulaires et navigation, trois critères font leur apparition :

  • 3.2.6 – Consistent Help : les mécanismes d’aide (chat, FAQ, contact) doivent apparaître au même endroit sur toutes les pages.
  • 3.3.7 – Redundant Entry : ne pas demander à l’utilisateur de ressaisir une information déjà fournie dans le même processus.
  • 3.3.8 – Accessible Authentication : les processus de connexion ne doivent pas reposer sur des tests cognitifs (CAPTCHA classique) sans alternative accessible.

Bon, certains de ces critères dépendent plus du contenu que du thème lui-même. Mais d’autres — notamment le 2.4.11 — ont un impact direct sur la façon dont on construit les layouts FSE.

Ce que le FSE implique pour l’accessibilité

Avec les thèmes classiques, le développeur contrôlait la structure HTML de bout en bout. Les templates PHP généraient un markup prévisible, et on savait exactement ce qui allait se retrouver dans le DOM.

Avec le Full Site Editing, c’est différent. Les templates sont composés de blocs, et le HTML est assemblé dynamiquement à partir des attributs enregistrés dans les fichiers JSON et les patterns. Ça crée trois types de risques concrets :

L’ordre de focus peut devenir imprévisible. Si un utilisateur réorganise des blocs dans l’éditeur, l’ordre de tabulation dans le rendu frontend peut ne plus correspondre à l’ordre visuel. C’est un vrai problème pour la navigation clavier (critère WCAG 2.4.3).

Les landmarks HTML (les balises <header>, <main>, <nav>, <footer>) ne sont pas toujours générés correctement par les blocs natifs. Par exemple, le bloc « Group » peut produire une <div> là où on attendrait une <section> ou un <aside> avec le bon rôle ARIA.

La hiérarchie des titres est peut-être le risque le plus fréquent. Dans un thème FSE, rien n’empêche techniquement un contenu d’utiliser un <h2> avant un <h1>, si le bloc Heading est mal configuré dans un template. Et ça, les outils d’audit ne le ratent pas.

Les pièges spécifiques aux thèmes en blocs

Voici les erreurs qu’on retrouve le plus souvent dans les thèmes FSE — même dans des thèmes bien conçus par ailleurs.

La hiérarchie des titres cassée. Le bloc Heading laisse l’éditeur (ou le thème lui-même) choisir librement le niveau h1 à h6. Si votre template de page d’archive utilise un bloc Heading configuré en h2 pour le titre de la page, sans aucun h1 au-dessus, vous êtes hors conformité. La solution : documenter et contraindre les niveaux de titres dans vos patterns et templates.

L’absence de landmarks ARIA. Beaucoup de thèmes FSE génèrent des structures entièrement composées de <div>, sans aucun rôle ARIA explicite ni balise sémantique. Les lecteurs d’écran ont alors du mal à naviguer par régions. Pensez à configurer l’attribut tagName de vos blocs Group et Column pour forcer les bonnes balises.

Les skip links mal implémentés. Le lien « Aller au contenu principal » est obligatoire pour la navigation clavier. Mais dans un thème FSE, il doit être placé manuellement dans le template header.html, et l’ancre cible (#wp-block-group ou un ID personnalisé) doit correspondre exactement au bloc <main>. C’est souvent raté.

Le mode sombre qui casse les contrastes. De plus en plus de thèmes FSE intègrent un toggle dark mode via theme.json ou du CSS custom. Problème : les palettes de couleurs sont rarement vérifiées en mode sombre, et les ratios de contraste (4.5:1 en AA) ne sont pas toujours respectés sur les variantes sombres. Ça passe visuellement mais ça échoue à l’audit.

Et enfin — c’est peut-être le piège le plus vicieux — le focus obscured par les sticky headers. Le critère 2.4.11 de WCAG 2.2 est directement visé ici : si votre header reste fixe en haut de page et que vous n’avez pas prévu de scroll-margin-top ou d’offset de focus, les éléments focalisés vont se retrouver cachés sous la barre de navigation. À corriger absolument.

Configurer theme.json pour l’accessibilité : les paramètres clés

C’est ici que tout se joue. Le fichier theme.json est bien plus qu’un simple fichier de configuration esthétique : c’est votre premier levier pour intégrer l’accessibilité dès la conception du thème. On va passer en revue les propriétés qui ont un impact direct sur la conformité WCAG 2.2, avec des exemples concrets à copier-coller.

La palette de couleurs : contraste et conformité WCAG AA

Le critère 1.4.3 exige un ratio de contraste d’au moins 4.5:1 pour le texte normal et 3:1 pour le texte large (18px et plus, ou 14px en gras) et les composants d’interface. Dans settings.color.palette, chaque couleur que vous définissez doit être pensée en paires : une couleur de texte + une couleur de fond compatibles.

Voici un exemple de palette conforme :

"settings": {
  "color": {
    "palette": [
      {
        "slug": "primary",
        "color": "#1a5276",
        "name": "Bleu principal"
      },
      {
        "slug": "on-primary",
        "color": "#ffffff",
        "name": "Texte sur bleu principal"
      },
      {
        "slug": "background",
        "color": "#f9f9f9",
        "name": "Fond clair"
      },
      {
        "slug": "text-dark",
        "color": "#1a1a1a",
        "name": "Texte principal"
      },
      {
        "slug": "accent",
        "color": "#c0392b",
        "name": "Accent rouge"
      }
    ],
    "duotone": [
      {
        "slug": "accessible-duo",
        "colors": ["#1a1a1a", "#f9f9f9"],
        "name": "Duotone accessible"
      }
    ]
  }
}

Le couple #1a1a1a sur #f9f9f9 atteint un ratio de 18.1:1 — largement au-dessus du minimum. Pour le #1a5276 sur blanc, on est à environ 7.2:1. Par contre, méfiez-vous des gris clairs très populaires en design : un #767676 sur blanc plafonne pile à 4.54:1, ce qui passe, mais laisse peu de marge.

Pour le duotone, le principe est le même : vérifiez que les deux tons choisis offrent un contraste suffisant entre eux. Un outil comme Colour Contrast Analyser ou simplement le checker intégré à Firefox DevTools peut vous y aider.

La typographie : unités relatives et zoom utilisateur

Le critère 1.4.4 exige que le texte puisse être agrandi à 200% sans perte de contenu ni de fonctionnalité. La règle de base : utiliser rem ou em plutôt que px dans settings.typography.fontSizes. Si vous définissez vos tailles en pixels, le zoom du navigateur les ignorera partiellement selon les configurations utilisateur.

"settings": {
  "typography": {
    "fontSizes": [
      {
        "slug": "small",
        "size": "0.875rem",
        "name": "Petit"
      },
      {
        "slug": "medium",
        "size": "1rem",
        "name": "Normal"
      },
      {
        "slug": "large",
        "size": "1.25rem",
        "name": "Grand"
      },
      {
        "slug": "x-large",
        "size": "1.75rem",
        "name": "Très grand"
      },
      {
        "slug": "heading",
        "size": "2.25rem",
        "name": "Titre principal"
      }
    ],
    "fluid": true
  }
}

L’option "fluid": true active la typographie fluide de WordPress (clamp CSS), ce qui est bien — mais attention : vérifiez que la taille minimale du clamp ne descend pas en dessous de 1rem pour le texte courant. C’est un piège classique avec les thèmes qui cherchent à être « responsive à tout prix ».

Le spacing : zones cliquables et critère 2.5.5

Le critère 2.5.5 (Target Size) impose une taille minimale de 44x44px pour les cibles interactives. settings.spacing vous permet de définir des espacements cohérents qui, combinés à vos styles de blocs, garantissent que les boutons et liens ne seront jamais trop petits ni trop serrés.

"settings": {
  "spacing": {
    "spacingSizes": [
      { "slug": "xs", "size": "0.5rem", "name": "Extra petit" },
      { "slug": "sm", "size": "0.75rem", "name": "Petit" },
      { "slug": "md", "size": "1rem", "name": "Moyen" },
      { "slug": "lg", "size": "1.5rem", "name": "Grand" },
      { "slug": "xl", "size": "2rem", "name": "Extra grand" }
    ],
    "padding": true,
    "margin": true,
    "units": ["px", "rem", "%", "vw"]
  }
}

En pratique, pour un bouton conforme 2.5.5, vous devez vous assurer qu’avec le padding défini dans styles.elements.button, la zone cliquable atteint bien les 44px. Un padding: 0.75rem 1.5rem sur une base de 1rem (16px) donne une hauteur d’environ 44px — c’est juste suffisant. Ajoutez min-height: 44px en CSS si vous n’êtes pas sûr.

Styles de liens : au-delà de la couleur seule

Le critère 1.4.1 est souvent mal compris : la couleur seule ne suffit pas à distinguer un lien du texte environnant. Il faut un indicateur visuel supplémentaire — le soulignement étant la solution la plus universelle.

"styles": {
  "elements": {
    "link": {
      "color": {
        "text": "var(--wp--preset--color--primary)"
      },
      "typography": {
        "textDecoration": "underline"
      },
      ":hover": {
        "typography": {
          "textDecoration": "none"
        },
        "color": {
          "text": "var(--wp--preset--color--accent)"
        }
      }
    }
  }
}

Ici, on garde le soulignement par défaut (état normal) et on peut le retirer au hover — c’est acceptable car l’état de repos est déjà différencié. Par contre, l’inverse (pas de soulignement par défaut, soulignement uniquement au hover) ne respecte pas le critère 1.4.1. C’est un choix de design qu’on voit souvent et qui pose problème.

Focus styles : boutons et critères 2.4.7 / 2.4.11

WCAG 2.2 a renforcé les exigences sur le focus visible avec le critère 2.4.11 (Focus Appearance). Le focus doit avoir un contour d’au moins 2px, avec un ratio de contraste de 3:1 entre l’état focusé et l’état non focusé. Fini le simple outline: none que certains thèmes ajoutent pour « faire joli ».

"styles": {
  "elements": {
    "button": {
      "color": {
        "background": "var(--wp--preset--color--primary)",
        "text": "var(--wp--preset--color--on-primary)"
      },
      "border": {
        "radius": "4px"
      },
      "spacing": {
        "padding": {
          "top": "0.75rem",
          "bottom": "0.75rem",
          "left": "1.5rem",
          "right": "1.5rem"
        }
      },
      ":focus-visible": {
        "outline": {
          "color": "var(--wp--preset--color--accent)",
          "offset": "3px",
          "width": "3px",
          "style": "solid"
        }
      }
    }
  }
}

Le :focus-visible (et non :focus) est la bonne pratique ici : il évite d’afficher l’outline au clic souris tout en le gardant pour la navigation clavier. WordPress FSE supporte cette pseudo-classe nativement depuis quelques versions. Et l’offset de 3px permet au contour de ne pas se confondre avec le fond du bouton, ce qui améliore significativement la lisibilité du focus.

Bon, je ne vais pas vous mentir : theme.json ne gère pas encore tout le CSS de focus de façon granulaire. Pour des cas complexes (cards cliquables, menus déroulants), vous aurez probablement besoin d’un fichier style.css complémentaire. Mais pour les éléments standards, cette configuration couvre l’essentiel.

La checklist WCAG 2.2 complète pour votre thème FSE

Bon, on rentre dans le vif du sujet. Cette checklist, c’est vraiment le cœur de cet article : un référentiel pratique à garder sous la main (ou à bookmarker) pour vérifier point par point la conformité de votre thème FSE. On la divise en quatre grandes catégories, du HTML de base jusqu’aux outils de test.

Structure HTML et navigation clavier

La fondation, c’est toujours le HTML. Un thème FSE accessible commence obligatoirement par une structure sémantique solide et une navigation au clavier irréprochable.

  • Skip link fonctionnel : un lien « Aller au contenu principal » visible au focus, positionné en tout premier dans le DOM — et qui pointe réellement vers le main avec un id correspondant
  • Landmarks HTML corrects : <header>, <main>, <nav>, <footer> doivent être présents et uniques (ou labelisés si vous en avez plusieurs)
  • Hiérarchie de titres logique : pas de saut de H2 à H4, pas de H1 manquant ou dupliqué — c’est un classique qui fait encore des dégâts
  • Focus visible sur tous les éléments interactifs : critères 2.4.7 (AA) et 2.4.11 (AA, nouveau en WCAG 2.2) — le focus ne doit jamais être masqué par un outline: none sans alternative visible
  • Navigation clavier complète :
    • Tab / Shift+Tab pour se déplacer entre les éléments
    • Entrée / Espace pour activer boutons et liens
    • Échap pour fermer les modales, menus déroulants ou dialogs
    • Aucun piège clavier (on doit toujours pouvoir « sortir » d’un composant)

Couleurs, contrastes et modes d’affichage

Les contrastes, c’est souvent là que les thèmes « jolis » échouent les audits. Et avec le dark mode maintenant quasi-universel, il faut vérifier deux fois plus.

  • Ratio texte/fond minimum :
    • Niveau AA : 4.5:1 pour le texte normal, 3:1 pour le grand texte (18px+ ou 14px+ en gras)
    • Niveau AAA : 7:1 pour le texte normal
  • Composants UI et états : 3:1 minimum pour les bordures de champs, icônes significatives, indicateurs de focus (critère 1.4.11)
  • Pas d’information transmise par la couleur seule (critère 1.4.1) : un lien doit se distinguer du texte par autre chose que sa couleur (souligné, icône, etc.)
  • Dark mode (prefers-color-scheme: dark) : vérifiez que vos CSS variables ou vos styles conditionnels maintiennent les ratios de contraste — ne réutilisez pas bêtement la même palette inversée
  • Animations et mouvements : implémentez prefers-reduced-motion pour désactiver ou réduire les transitions, parallaxes et animations (critère 2.3.3 AAA, mais bonne pratique universelle)

Formulaires, médias et interactions

C’est la partie la plus souvent bâclée, surtout sur les thèmes FSE où les blocs de formulaire sont gérés par des plugins tiers. Ne déléguez pas entièrement cette responsabilité au plugin.

  • Labels associés aux champs : chaque <input> doit avoir un <label> lié via for/id, ou un aria-label / aria-labelledby en dernier recours — jamais de placeholder seul
  • Messages d’erreur explicites : l’erreur doit indiquer quel champ est concerné et comment le corriger (critère 3.3.1 et 3.3.3)
  • Images avec alt text : alt vide (alt="") pour les images décoratives, alt descriptif pour les images porteuses de sens
  • Vidéos avec sous-titres : critère 1.2.2 (AA) — les sous-titres doivent être synchronisés
  • Pas de contenu clignotant : rien qui clignote plus de 3 fois par seconde (critère 2.3.1) — ça vaut aussi pour les animations CSS
  • Authentification accessible (critère 3.3.8, nouveau WCAG 2.2) : ne pas exiger de mémorisation ou de transcription d’informations lors de la connexion sans alternative (captcha cognitif à éviter ou contourner)
  • Pas de drag-and-drop obligatoire (critère 2.5.7, nouveau WCAG 2.2) : toute action réalisable par glisser-déposer doit avoir une alternative par pointer ou clavier

Tester et valider l’accessibilité de votre thème

Avoir une checklist, c’est bien. La vérifier avec les bons outils, c’est mieux. Voici ce que j’utilise concrètement.

Outils automatisés :

  • Axe DevTools (extension Chrome/Firefox, gratuite) : c’est la référence, zéro faux positif dans les règles de base, et les explications sont claires
  • WAVE (WebAIM) : disponible en extension ou en ligne, très visuel — idéal pour repérer les erreurs de structure et de contraste
  • Lighthouse (intégré dans Chrome DevTools, onglet « Accessibilité ») : pratique pour un score rapide, mais attention — un score de 100 ne signifie pas une conformité totale
  • Validateur HTML du W3C : indispensable, un HTML invalide peut casser des comportements d’accessibilité sans que les outils de test le signalent

Tests manuels :

  • Navigation au clavier : débranchez votre souris 5 minutes et naviguez uniquement au Tab — vous serez surpris de ce que vous découvrez
  • Lecteur d’écran : NVDA (gratuit, Windows) ou VoiceOver (natif Mac/iOS) — testez au minimum la page d’accueil et un formulaire de contact
  • Plugin WordPress WP Accessibility de Joe Dolson : un excellent complément pour corriger certains problèmes communs de WordPress (skip links, tabindex, etc.) sans modifier le code du thème

Rappel important : les outils automatisés détectent environ 30 à 40 % des problèmes d’accessibilité. Les tests manuels et avec lecteur d’écran restent indispensables pour une validation sérieuse.