Composant de contenu dépliable organisé en items. Chaque item révèle son contenu au clic via une animation fluide. Supporte le mode "single" pour n'ouvrir qu'un panneau à la fois.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus alias, consectetur culpa cumque debitis dolorum fugiat iste, iusto magnam mollitia nam numquam obcaecati praesentium quae quos reiciendis similique tempora voluptatum ?
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus alias, consectetur culpa cumque debitis dolorum fugiat iste, iusto magnam mollitia nam numquam obcaecati praesentium quae quos reiciendis similique tempora voluptatum ?
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus alias, consectetur culpa cumque debitis dolorum fugiat iste, iusto magnam mollitia nam numquam obcaecati praesentium quae quos reiciendis similique tempora voluptatum ?
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus alias, consectetur culpa cumque debitis dolorum fugiat iste, iusto magnam mollitia nam numquam obcaecati praesentium quae quos reiciendis similique tempora voluptatum ?
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus alias, consectetur culpa cumque debitis dolorum fugiat iste, iusto magnam mollitia nam numquam obcaecati praesentium quae quos reiciendis similique tempora voluptatum ?
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus alias, consectetur culpa cumque debitis dolorum fugiat iste, iusto magnam mollitia nam numquam obcaecati praesentium quae quos reiciendis similique tempora voluptatum ?
Chaque data-target doit correspondre exactement à l’
id du panneau associé. Vous pouvez utiliser
# ou non — le JavaScript gère les deux cas.
⚠️ Ne pas ajouter de margin ou de
padding directement sur le panneau pour garantir une
animation fluide.
Utilisez .accordion-body pour gérer les espacements.
Les attributs suivants sont automatiquement ajoutés à l’initialisation :
aria-expanded (état ouvert / fermé)aria-controls (lien vers le panneau)aria-labelledby (si le bouton possède un
id)
role="region" (zone de contenu
accessible) à rajouter sur le panel si c'est un élément important.
Vous n’avez rien à gérer manuellement côté accessibilité — mais c’est toujours mieux d’y penser 😉
| CLASSE | ÉLÉMENT | DESCRIPTION |
|---|---|---|
.accordion |
<div> |
Conteneur principal avec bordure, border-radius et gestion du débordement. |
.accordion-item |
<div> |
Conteneur d’un item (structure uniquement, pas de style direct). |
.accordion-btn |
<button> |
Bouton déclencheur en pleine largeur avec gestion des bordures et de l’état via aria-expanded.
|
.accordion-body |
<div> |
Contenu du panneau avec padding via variables CSS. |
.accordion-indicator |
<span> |
Icône via ::after, animée selon l’état du bouton
(.is-open).
|
.accordion-btn-sm |
<button> |
Paddings réduits. |
.accordion-btn-md |
<button> |
Paddings intermédiaires (par défaut). |
.accordion-btn-lg |
<button> |
Paddings augmentés. |
Plusieurs panneaux peuvent être ouverts simultanément.
Un seul panneau ouvert à la fois. Le JS ferme automatiquement les autres panneaux à l'ouverture d'un nouveau.
Les modificateurs de taille s'appliquent sur chaque .accordion-btn individuellement via les tokens CSS dédiés.
| ÉTAT | ÉLÉMENT | DESCRIPTION |
|---|---|---|
| Ouvert | [aria-expended="true"] |
L'indicateur change de contenu. Le panneau est visible (hidden
retiré).
|
| Fermé | [aria-expended="false"] |
Panneau avec attribut hidden. C'est l'état initial
par défaut.
|
| En animation | [data-animating] |
Attribut temporaire posé par le JS. Bloque les clics répétés pendant l'animation (200 ms). |
| Focus | :focus-visible |
Contour visible sur le bouton lors de la navigation clavier (à styler via CSS). |
Le composant est piloté par la classe Collapse. Elle s'appuie
sur la délégation d'événements (un seul
listener sur document) et utilise l'API Web Animations pour
les transitions.
import Collapse from './Collapse.js';
// A single instance is enough for the entire page.
new Collapse();
La classe implémente un guard Collapse.initialized :
instancier Collapse plusieurs fois n'entraîne aucun
doublon de listeners.
| ATTRIBUT | ÉLÉMENT | DESCRIPTION |
|---|---|---|
data-ui="accordion" |
.accordion |
Marque le wrapper pour la gestion du mode single. |
data-type="single" |
.accordion |
Active le mode exclusif : un seul panneau ouvert à la fois. |
data-ui="collapse" |
.accordion-btn |
Identifie le bouton comme déclencheur du "collapse". |
data-target |
.accordion-btn |
Sélecteur de l'élément panneau cible. Accepte #id ou
id.
|
| MÉTHODE | DESCRIPTION |
|---|---|
Collapse.init() |
Initialise aria-controls et aria-expanded sur tous les boutons [data-ui="collapse"] du DOM.
|
Collapse.toggle(panel, button)
|
Bascule l'état du panneau. Appelle open ou close selon panel.hidden.
|
Collapse.open(panel, button) |
Ouvre un panneau avec animation. Met à jour aria-expanded="true".
Appelle handleAccordion.
|
Collapse.close(panel, button)
|
Ferme un panneau avec animation. Repose hidden en fin
d'animation.
|
Collapse.handleAccordion(button)
|
Si le parent est data-type="single", ferme tous les
autres panneaux ouverts.
|
L'ouverture et la fermeture sont gérées par panel.animate()
(Web Animations API), avec une durée de 200 ms et
un easing ease. Un attribut data-animating est posé pendant la transition pour éviter les
clics
parasites.
// Open a panel programmatically
const panel =
document.getElementById('mon-panel');
const btn = document.querySelector('[data-target="#mon-panel"]');
Collapse.open(panel, btn);
// Close programmatically
Collapse.close(panel, btn);
| TOKEN | RÔLE |
|---|---|
--accordion-border-width |
Épaisseur des bordures |
--accordion-border-style |
Style de bordure (solid, dashed…)
|
--accordion-border-radius |
Rayon des coins du wrapper |
--accordion-border-color |
Couleur des bordures |
--accordion-background-color |
Couleur de fond de l’accordéon |
--accordion-body-padding-x |
Padding horizontal du corps |
--accordion-body-padding-y |
Padding vertical du corps |
--accordion-button-padding-x |
Padding horizontal du bouton (défaut) |
--accordion-button-padding-y |
Padding vertical du bouton (défaut) |
--accordion-button-padding-x-sm
|
Padding horizontal — taille sm |
--accordion-button-padding-y-sm
|
Padding vertical — taille sm |
--accordion-button-padding-x-md
|
Padding horizontal — taille md |
--accordion-button-padding-y-md
|
Padding vertical — taille md |
--accordion-button-padding-x-lg
|
Padding horizontal — taille lg |
--accordion-button-padding-y-lg
|
Padding vertical — taille lg |
--accordion-button-background-color
|
Couleur de fond de l’accordéon bouton |
--accordion-indicator-content
|
Contenu de l'indicateur |
/* Global variables */
:root {
--accordion-border-radius: 8px;
--accordion-button-padding-x: 1.5rem;
--accordion-button-padding-y: 1.125rem;
}
/* Light theme */
:root[data-theme="light"] {
color-scheme:
light;
--accordion-border-color:
#222222;
}
/* Dark theme */
:root[data-theme="dark"] {
color-scheme:
dark;
--accordion-border-color:
#888888;
}
| PRATIQUE | DÉTAIL |
|---|---|
aria-expanded |
Posé et mis à jour automatiquement par le JS sur chaque bouton. Communique l'état ouvert/fermé aux lecteurs d'écran. |
aria-controls |
Lie le bouton à son panneau via l'id. Initialisé par
Collapse.init() si absent.
|
aria-labelledby |
Associe le panneau à son bouton déclencheur via l'id
du bouton. Permet aux lecteurs d'écran d'annoncer correctement le libellé du panneau. Ajouté
automatiquement par Collapse.init() lorsque le bouton
possède un id.
|
hidden |
L'attribut HTML natif masque le panneau aux technologies d'assistance et aux moteurs de recherche. |
Élément <button> |
Utilisez toujours un <button> (pas un <div>) pour assurer la navigation clavier native
(Tab, Entrée, Espace).
|
| Focus visible | Stylez :focus-visible sur .accordion-btn
pour les utilisateurs clavier.
|
role="region" |
Définit le panneau comme une région accessible pour les technologies d’assistance. À rajouter si le panel est important. |
N'utilisez pas display: none à la place de hidden : le JS anime la hauteur et repose l'attribut natif
en
fin d'animation. Toute surcharge CSS peut casser le comportement.
Toujours ajouter hidden sur les panneaux fermés au
chargement. Sans cet attribut, les panneaux sont considérés comme ouverts par défaut.
Placer l'.accordion-indicator en dernier dans le bouton
pour qu'il
soit poussé à droite avec par le justify-content:
space-between; du .accordion-btn.
Ne pas instancier Collapse avant le chargement du DOM.
Utilisez DOMContentLoaded ou placez le script en bas de
page.
L'animation repose sur la Web Animations API (element.animate()), supportée par tous les navigateurs
modernes. Pour IE11, un polyfill est nécessaire.
Accordion · WEBDEV-UI DOCS / V1