Accordéon

Un accordéon permet l'affichage d'une liste d'éléments empilés dont le contenu est révélé par un système de plier / déplier.

Règles d’implémentation pour l’accessibilité

  • Chaque en-tête de l’accordéon est codé avec une titraille. En fonction de la struture de sa page, le niveau de titre sera adpaté pour conserver l’ordre logique de numérotation.
  • Le titre de chaque en-tête de l’accordéon contient un élément button. L’élément bouton est le seul élément à l’intérieur de l’élément titre. Autrement dit, s’il existe d’autres éléments visibles, ils ne sont pas inclus dans l’élément d’en-tête.
  • L’élément button a les caractériqtiques suivantes :
    • un attribut aria-controls qui fait référence à l’id de l’élément qu’il contrôle (dit « panneau ») ;
    • un attribut aria-expanded qui prend la valeur :
      • true quand le panneau géré par le bouton d’en-tête de l’accordéon est visible ;
      • false quand le panneau géré par le bouton d’en-tête de l’accordéon est invisible.
  • Si le panneau d’accordéon géré par le bouton d’en-tête de l’accordéon est visible, et bouton d’en-tête de l’accordéon ne permet pas de réduire le panneau, l’élément du bouton d’en-tête a aria-disabled défini sur true (<button aria-disabled="true...>).
  • Chaque panneau a le rôle region et un id avec une valeur qui fait référence au bouton qui en contrôle l’affichage.
    La région de rôle est particulièrement utile pour la perception de la structure par les utilisateurs de lecteurs d’écran lorsque les panneaux contiennent des éléments d’en-tête ou un accordéon imbriqué.

Visuel

Extraits de code

Code HTML

<div class="accordeon">
    <h3>
        <button type="button" aria-expanded="true" class="accordeon-bouton" aria-controls="contenu1" id="accordeon1">
            Intitulé accordéon 1
        </button>
    </h3>
    <div id="contenu1" role="region" aria-labelledby="accordeon1" class="accordeon-panneau">
            <p>Consectetur cupidatat nisi amet exercitation quis mollit. Incididunt labore voluptate labore
                nostrud incididunt fugiat labore est anim tempor et Lorem dolor ea. Est aute sint velit deserunt
                qui adipisicing magna cillum fugiat et exercitation. Consectetur excepteur aliquip duis
                consectetur minim tempor amet sint fugiat duis irure do. Laboris magna cupidatat sint enim non
                occaecat cillum anim consectetur mollit laboris anim. Ea velit fugiat nisi aliquip labore sit
                Lorem laborum mollit sit culpa non sunt.</p>
            <p>Consectetur cupidatat nisi amet exercitation quis mollit. Incididunt labore voluptate labore
                nostrud incididunt fugiat labore est anim tempor et Lorem dolor ea. Est aute sint velit deserunt
                qui adipisicing magna cillum fugiat et exercitation. Consectetur excepteur aliquip duis
                consectetur minim tempor amet sint fugiat duis irure do. Laboris magna cupidatat sint enim non
                occaecat cillum anim consectetur mollit laboris anim. Ea velit fugiat nisi aliquip labore sit
                Lorem laborum mollit sit culpa non sunt.</p>
    </div>
    <h3>
        <button type="button" aria-expanded="false" class="accordeon-bouton" aria-controls="contenu2" id="accordeon2">
            Intitulé accordéon 2
        </button>
    </h3>
    <div id="contenu2" role="region" aria-labelledby="accordeon2" class="accordeon-panneau" hidden="">
            <p>Consectetur cupidatat nisi amet exercitation quis mollit. Incididunt labore voluptate labore
                nostrud incididunt fugiat labore est anim tempor et Lorem dolor ea. Est aute sint velit deserunt
                qui adipisicing magna cillum fugiat et exercitation. Consectetur excepteur aliquip duis
                consectetur minim tempor amet sint fugiat duis irure do. Laboris magna cupidatat sint enim non
                occaecat cillum anim consectetur mollit laboris anim. Ea velit fugiat nisi aliquip labore sit
                Lorem laborum mollit sit culpa non sunt.</p>
            <p>Consectetur cupidatat nisi amet exercitation quis mollit. Incididunt labore voluptate labore
                nostrud incididunt fugiat labore est anim tempor et Lorem dolor ea. Est aute sint velit deserunt
                qui adipisicing magna cillum fugiat et exercitation. Consectetur excepteur aliquip duis
                consectetur minim tempor amet sint fugiat duis irure do. Laboris magna cupidatat sint enim non
                occaecat cillum anim consectetur mollit laboris anim. Ea velit fugiat nisi aliquip labore sit
                Lorem laborum mollit sit culpa non sunt.</p>
    </div>
    <h3>
        <button type="button" aria-expanded="false" class="accordeon-bouton" aria-controls="contenu3" id="accordeon3">
            Intitulé accordéon 3
        </button>
    </h3>
    <div id="contenu3" role="region" aria-labelledby="accordeon3" class="accordeon-panneau" hidden="">
            <p>Consectetur cupidatat nisi amet exercitation quis mollit. Incididunt labore voluptate labore
                nostrud incididunt fugiat labore est anim tempor et Lorem dolor ea. Est aute sint velit deserunt
                qui adipisicing magna cillum fugiat et exercitation. Consectetur excepteur aliquip duis
                consectetur minim tempor amet sint fugiat duis irure do. Laboris magna cupidatat sint enim non
                occaecat cillum anim consectetur mollit laboris anim. Ea velit fugiat nisi aliquip labore sit
                Lorem laborum mollit sit culpa non sunt.</p>
            <p>Consectetur cupidatat nisi amet exercitation quis mollit. Incididunt labore voluptate labore
                nostrud incididunt fugiat labore est anim tempor et Lorem dolor ea. Est aute sint velit deserunt
                qui adipisicing magna cillum fugiat et exercitation. Consectetur excepteur aliquip duis
                consectetur minim tempor amet sint fugiat duis irure do. Laboris magna cupidatat sint enim non
                occaecat cillum anim consectetur mollit laboris anim. Ea velit fugiat nisi aliquip labore sit
                Lorem laborum mollit sit culpa non sunt.</p>
    </div>
</div>

Code CSS

Pour adapter la couleur de la barre de navigation et des liens, modifier les codes couleurs dans la déclaration :root.

:root {
    --accordeon-width: 50%;
    --acccordeon-border-radius: 0;
    --accordeon-border-color: #858585;
    --accordeon-entete-color: #212121;
    --accordeon-entete-hover-background-color: #e1edfe;
    --accordeon-entete-hover-color: #0759d5;
    --accordeon-focus-border-color: #0759d5;
    --accordeon-focus-within-background-color: #f7f7f7;
}

.accordeon {
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--accordeon-border-color);
    border-bottom: 1px solid var(--accordeon-border-color);
    width: var(--accordeon-width);
}

.accordeon h3 {
    margin: 0 !important;
    padding: 0;
}

.accordeon>*+* {
    border-top: 1px solid var(--accordeon-border-color);
}

.accordeon-bouton {
    color: var(--accordeon-entete-color);
    background-color: transparent;
    border:0;
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.5rem;
    margin: 0;
    max-height: none;
    max-width: 100%;
    min-height: 3rem;
    overflow: initial;
    padding: .75rem 1rem;
    text-align: left;
    width: 100%;
}
.accordeon-bouton::after {
  --icon-size: 1.5rem;
  content: "";
  background-color: currentColor;
  float: right;
  flex: none;
  height: var(--icon-size);
  -webkit-mask-size: 100% 100%;
  mask-size: 100% 100%;
  vertical-align: calc((0.55em - var(--icon-size)) * 0.5);
  width: var(--icon-size);
  -webkit-mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCI+PHBhdGggZD0ibTEyIDE2LTYtNmgxMmwtNiA2WiIvPjwvc3ZnPg==);
  mask-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCI+PHBhdGggZD0ibTEyIDE2LTYtNmgxMmwtNiA2WiIvPjwvc3ZnPg==);
  transition: transform 0.2s ease-out;
}
.accordeon-bouton[aria-expanded="true"] {
    font-weight: bold;
    background-color: var(--accordeon-entete-hover-background-color);
}
.accordeon-bouton[aria-expanded="true"]::after {
    transform: rotate(180deg);
}
.accordeon-bouton:focus,
.accordeon-bouton:hover {
    background: var(--accordeon-entete-hover-background-color);
}

.accordeon-panneau {
    margin: 0;
    padding: 1em 0;
}

/* Gestion bug Edge  */
.accordeon-panneau[hidden] {
    display: none;
}

Code javascript


"use strict";

class Accordion {
  constructor(domNode) {
    this.rootEl = domNode;
    this.buttonEl = this.rootEl.querySelector("button[aria-expanded]");

    const controlsId = this.buttonEl.getAttribute("aria-controls");
    this.contentEl = document.getElementById(controlsId);

    this.open = this.buttonEl.getAttribute("aria-expanded") === "true";

    // ajout de l'écouteur sur le clic
    this.buttonEl.addEventListener("click", this.onButtonClick.bind(this));
  }

  onButtonClick() {
    this.toggle(!this.open);
  }

  toggle(open) {
    // on ne fait rien si le statut open n'a pas changé
    if (open === this.open) {
      return;
    }

    // mise à jour de l'état interne
    this.open = open;

    // modification de l'attribut
    this.buttonEl.setAttribute("aria-expanded", `${open}`);
    if (open) {
      this.contentEl.removeAttribute("hidden");
    } else {
      this.contentEl.setAttribute("hidden", "");
    }
  }
  
  open() {
    this.toggle(true);
  }

  close() {
    this.toggle(false);
  }
}

// initialisation de l'accordéon. Remplacer h3 par une autre titraille si besoin
const accordions = document.querySelectorAll(".accordion h3");
accordions.forEach((accordionEl) => {
  new Accordion(accordionEl);
});