← Retour à la liste
★★★★½ 4.5 / 5
Catégorie 06ART.

Accessibility Tools

Widget d'accessibilité Drupal — 11 plugins, sans jQuery, cookie persistant

Installation
Installation Composercomposer require drupal/accesstools drush en a11y -y drush cr
Activer et configurer les plugins# Après activation, les plugins par défaut sont déjà configurés # (config/install/*.yml importés automatiquement) # Vérifier la liste des plugins activés : drush config:get --all | grep "a11y.a11y" # Interface d'administration : # → /admin/config/system/accessibility/a11y
Exporter la configuration dans le projetdrush config:export # → config/sync/a11y.a11y.contrast.yml # → config/sync/a11y.a11y.textsize.yml # → config/sync/a11y.a11y.textspacing.yml # → ...11 fichiers au total git add config/sync/a11y.a11y.*.yml git commit -m "feat: configure accesstools plugins"
Désactiver un plugin spécifique# Via l'interface : /admin/config/system/accessibility/a11y # → Cliquer "Delete" sur le plugin à désactiver # Via drush (supprimer l'entité de config) : drush config:delete a11y.a11y.audioreader drush cr
Version2.3.0 (avril 2026)
PrixGratuit — GPL-2.0-or-later
Plateformes
LinuxmacOSWindows
Commandes6
Exemples4
ART
À propos

Accessibility Tools (machine name: a11y) est un module Drupal contrib qui injecte un widget d'accessibilité configurable sur toutes les pages du site via hook_page_bottom(). Chaque fonctionnalité est un plugin indépendant (système de plugin Discovery) stocké comme entité de configuration. Aucun compte utilisateur requis — les préférences sont persistées par cookies. Écrit en vanilla JavaScript (zero jQuery), utilisant uniquement js-cookie. Compatible Drupal 9, 10, 11. Couvert par la politique de sécurité Drupal.

Fonctionnalités clés
11 plugins indépendants — activables à la carteChaque outil d'accessibilité est un plugin Discovery autonome : Contrast, Invert, OpenDyslexic, TextSize, TextSpacing, Animation, Cursor, Keyboard, ReadingMask, FocusMode, AudioReader. Activez uniquement ceux dont votre site a besoin via l'interface d'administration.
Injection automatique via hook_page_bottom()Le widget s'affiche sur toutes les pages sans configurer de bloc ni modifier le thème. hook_page_bottom() charge les librairies JS/CSS uniquement pour les plugins activés — zéro surcharge si un plugin est désactivé.
TextSpacing — conformité WCAG 1.4.12Applique les espacements minimaux WCAG 1.4.12 d'un toggle : line-height ≥ 1.5×, letter-spacing ≥ 0.12em, word-spacing ≥ 0.16em, paragraph-spacing ≥ 2em. Tout ce qui doit fonctionner fonctionne — aucun contenu ne doit se superposer.
TextSize — slider 5 niveaux sur document.documentElementSlider de taille de texte avec 5 niveaux discrets : XS (85%), S (92.5%), Moy. (100%), L (110%), XL (120%). Appliqué sur html (documentElement.style.fontSize) — le rem cascade dans tous les éléments. Rétrocompatible avec les boutons V1.
AudioReader — Web Speech API, lecture au clicQuand actif, un clic sur n'importe quel élément texte (p, h1-h6, li, td, blockquote, figcaption...) déclenche window.speechSynthesis. La langue détectée depuis document.documentElement.lang (fr-FR par défaut). L'élément en cours de lecture reçoit la classe a11y-audioreader-reading pour un feedback visuel.
ReadingMask — masque de lecture avec suivi sourisCrée un overlay pleine page avec une bande transparente de 80px qui suit le curseur souris (mousemove). L'utilisateur voit uniquement la ligne en cours de lecture, le reste est assombri à 55% d'opacité. Aide la dyslexie et l'ADHD.
FocusMode — réduction de bruit visuelAjoute body.a11y-focusmode. Le CSS cible les sidebars, images décoratives, bannières et éléments non essentiels pour les masquer. L'utilisateur se concentre sur le contenu principal sans distraction.
Persistance cookies — sans compte utilisateurChaque plugin stocke son état dans un cookie a11y_{plugin} via js-cookie@3.0.1. Lors du rechargement de page, chaque plugin lit son cookie en init() et restaure l'état. Aucun compte, aucune session serveur — fonctionne pour les utilisateurs anonymes.
Commandes
CommandeDescription
/admin/config/system/accessibility/a11yListe des plugins activés — ajouter, configurer, supprimer
/admin/config/system/accessibility/a11y/addAjouter un nouveau plugin (sélection parmi les plugins découverts)
drush config:exportExporter les entités a11y.a11y.* dans config/sync/
drush config:importImporter la configuration du module depuis config/sync/
drush config:delete a11y.a11y.{plugin}Désactiver un plugin spécifique (ex: a11y.a11y.audioreader)
drush en a11y -yActiver le module et importer la configuration par défaut
Exemples
Override du template widget pour personnaliser le boutonCODE
{# themes/mon_theme/templates/a11y-widget.html.twig #}
{# Surcharge du widget complet — bouton trigger personnalisé #}

<div class="a11y-widget mon-theme-a11y">
  <button
    class="a11y-widget-trigger"
    aria-label="{{ 'Accessibilité' | t }}"
    aria-expanded="false"
    aria-controls="a11y-panel"
  >
    {# Icône personnalisée du thème #}
    {{ source('@mon_theme/images/a11y-icon.svg') }}
  </button>

  <div
    id="a11y-panel"
    class="a11y-widget-panel"
    hidden
    role="dialog"
    aria-label="{{ 'Outils d\'accessibilité' | t }}"
  >
    {# Ré-inclure les sections du template parent #}
    {% if plugins.contrast %}...{% endif %}
    {# ... #}
  </div>
</div>
Cibler les éléments cachés en FocusMode dans le CSS thèmeCODE
/* themes/mon_theme/css/a11y.css */
/* body.a11y-focusmode — masquer les éléments non essentiels */

body.a11y-focusmode .layout-sidebar-first,
body.a11y-focusmode .layout-sidebar-second,
body.a11y-focusmode .region-footer-top,
body.a11y-focusmode .views-element-container:not(.main-content *),
body.a11y-focusmode [aria-hidden="true"],
body.a11y-focusmode .decorative-image,
body.a11y-focusmode .block-system-breadcrumb-block {
  display: none !important;
}

body.a11y-focusmode .layout-main {
  max-width: 72ch;
  margin-inline: auto;
  font-size: 1.05rem;
  line-height: 1.7;
}
Résoudre le conflit CDN jsDelivr avec une CSP stricteCODE
# Option 1 : héberger js-cookie localement via un module custom
# Télécharger : https://cdn.jsdelivr.net/npm/js-cookie@3.0.1/dist/js.cookie.min.js
# → web/modules/custom/mon_module/js/js.cookie.min.js

# Surcharger la librairie global dans mon_module.libraries.yml :
a11y/global:
  version: override
  css:
    base:
      /modules/contrib/accesstools/plugins/global/global.css: {}
  js:
    js/js.cookie.min.js: {minified: true}

# Option 2 : autoriser jsDelivr dans la CSP (next.config.ts ou nginx)
# script-src 'self' https://cdn.jsdelivr.net;

# Option 3 (Drupal) : ajouter dans settings.php :
$config['system.performance']['js']['preprocess'] = TRUE;
# Et configurer le Content-Security-Policy via le module seckit :
# composer require drupal/seckit
Vérifier les cookies posés en console navigateurCODE
// Console navigateur — vérifier l'état de tous les plugins :
document.cookie.split(';')
  .filter(c => c.trim().startsWith('a11y_'))
  .forEach(c => console.log(c.trim()));

// Résultat attendu (si textspacing et contrast activés) :
// a11y_textspacing=true
// a11y_contrast=true
// a11y_textsize=1.1

// Réinitialiser toutes les préférences accesstools :
document.cookie.split(';')
  .filter(c => c.trim().startsWith('a11y_'))
  .forEach(c => {
    const name = c.trim().split('=')[0];
    document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
  });
Points forts & faibles
Points forts
+Zéro jQuery — vanilla JS pur, js-cookie comme seule dépendance externe
+Injection automatique sans placement de bloc ni modification de thème
+Architecture plugin extensible — ajoutez vos propres plugins dans un module custom
+Entités de configuration — exportables avec drush config:export et versionnables
+CSS scoping propre sous body.a11y-{plugin} — aucune variable JS globale
+Widget V2 accessible — role="switch", role="dialog", aria-checked, aria-expanded
+Couvert par la politique de sécurité Drupal
+Multilingue — toutes les chaînes passent par t() et sont traduisibles
+WCAG 1.4.12 (TextSpacing) et WCAG 2.4.7 (Keyboard) couverts nativement
Points faibles
js-cookie chargé depuis CDN jsDelivr (violation potentielle de la CSP stricte)
AudioReader dépend de Web Speech API — non supporté sur tous les navigateurs (Firefox partiel, Safari limité)
FocusMode nécessite un CSS thème spécifique pour identifier les sidebars correctement
TextSize appliqué sur documentElement — peut interférer avec des thèmes qui fixent font-size en px sur html
ReadingMask basé sur mousemove — pas adapté aux utilisateurs clavier/tactile
Pas de sous-module séparé pour les tests Behat/PHPUnit fournis
Verdict

Une solution d'accessibilité Drupal solide, légère et architecturée proprement. Le plugin system permet de l'étendre sans toucher au module. La V2 widget est nettement supérieure à la V1 en accessibilité intrinsèque. Quelques points à surveiller — CDN jsDelivr et Web Speech API — selon les contraintes du projet.

Tout projet Drupal 9/10/11 devant respecter le RGAA ou les WCAG 2.1 AA. Indispensable pour les sites publics français (loi EAAI, référentiel RGAA 4.1). À combiner avec une politique d'accessibilité et des audits WAVE/axe réguliers.