Accordion Basic
Sections repliables en CSS pur : animation max-height fluide, chevron rotatif, multi-ouverture par défaut ou mode exclusif via un seul paramètre.
Cet effet est gratuit — la catégorie Navigation en contient 36 au total, dont 4 gratuits. Effect.Labs regroupe 811 effets vanilla. Découvrir la catégorie →
Exemples d'usage
20 · Max : 100limit pour la pagination.1navigation, particles, loadersComment ça marche
L'ouverture repose sur l'astuce CSS max-height : chaque .accordion-content part à max-height: 0; overflow: hidden. Quand la classe .active est posée sur l'item parent, la règle .accordion-item.active .accordion-content { max-height: 200px } entre en jeu et le navigateur interpole entre les deux valeurs via transition: max-height 0.4s. L'overflow: hidden pré-existant coupe proprement le contenu pendant le voyage.
Le chevron est un SVG inline animé par une seule règle CSS : .accordion-item.active .accordion-icon { transform: rotate(180deg) } avec transition: transform 0.3s. Le bouton .accordion-header obtient un léger fondu de fond au survol (transition: background 0.3s) — les deux transitions sont indépendantes et composables.
La fonction toggleAccordion(header, type) est globale (non encapsulée dans un IIFE), appelée directement depuis l'attribut onclick de chaque bouton. Elle remonte vers l'item (header.parentElement) puis vers l'accordéon (.parentElement). En mode 'single', elle retire d'abord .active de tous les autres items avant de basculer l'item courant — une seule section reste ouverte. En mode 'basic', elle bascule simplement l'item sans toucher aux voisins.
Le variant CSS .accordion-single est une couche optionnelle : ajouter cette classe sur .accordion ajoute une bordure indigo (rgba(99,102,241,0.2)) sur chaque item et un box-shadow lumineux sur l'item actif. Aucun JS supplémentaire n'est requis — uniquement un changement de classe HTML.
Accessibilité
- prefers-reduced-motion non implémenté : les transitions
max-heightettransforms'exécutent quelle que soit la préférence système. Ajoutez@media (prefers-reduced-motion: reduce) { .accordion-content, .accordion-icon { transition: none; } }pour corriger. - aria-expanded absent : les boutons n'exposent pas leur état ouvert/fermé aux lecteurs d'écran. Pour la conformité WCAG 4.1.2, ajoutez
aria-expanded="false"par défaut et basculez-le àtruedanstoggleAccordion. - Clavier : les éléments
<button>sont nativement focusables et activables par Espace / Entrée — aucun JS supplémentaire requis. - Contraste : texte blanc (
#ffffff) sur fond sombre (rgba(255,255,255,0.05)) — ratio supérieur à 7:1, conforme WCAG AA et AAA. - onclick inline : les gestionnaires sont sur des
<button>natifs — accessibles sans CSS et dans le flux de tabulation par défaut.
Compatibilité navigateur
Repose uniquement sur des transitions CSS (max-height, transform) et la manipulation de classes — fonctionnalités disponibles depuis 2013.
Sans JavaScript, les boutons sont inactifs et les sections restent dans leur état initial (la première pré-ouverte via la classe <code>.active</code> en HTML). Aucune erreur JS fatale.
Le code
Copiez les trois blocs dans votre page. Aucune dépendance.
<div class="component-demo">
<div class="accordion" id="accordionBasic">
<div class="accordion-item active">
<button class="accordion-header" onclick="toggleAccordion(this, 'basic')">
Section 1
<svg class="accordion-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6">
</path>
</svg>
</button>
<div class="accordion-content">
<div class="accordion-body">
Contenu de la première section avec animation de hauteur fluide.
</div>
</div>
</div>
<div class="accordion-item">
<button class="accordion-header" onclick="toggleAccordion(this, 'basic')">
Section 2
<svg class="accordion-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6">
</path>
</svg>
</button>
<div class="accordion-content">
<div class="accordion-body">
Deuxieme section avec du contenu different.
</div>
</div>
</div>
<div class="accordion-item">
<button class="accordion-header" onclick="toggleAccordion(this, 'basic')">
Section 3
<svg class="accordion-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M6 9l6 6 6-6">
</path>
</svg>
</button>
<div class="accordion-content">
<div class="accordion-body">
Troisieme et dernière section.
</div>
</div>
</div>
</div>
</div>
.component-demo {
width: 100%;
min-height: 200px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 12px;
}
.accordion {
width: 100%;
max-width: 350px;
}
.accordion-item {
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
margin-bottom: 8px;
overflow: hidden;
}
.accordion-header {
width: 100%;
padding: 16px 20px;
background: transparent;
border-width: medium;
border-style: none;
border-color: currentcolor;
border-image: initial;
color: white;
font-size: 0.95rem;
font-weight: 500;
font-family: inherit;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
transition: background 0.3s;
}
.accordion-header:hover {
background: rgba(255, 255, 255, 0.05);
}
.accordion-icon {
transition: transform 0.3s;
}
.accordion-item.active .accordion-icon {
transform: rotate(180deg);
}
.accordion-content {
max-height: 0px;
overflow: hidden;
transition: max-height 0.4s, padding 0.3s;
}
.accordion-item.active .accordion-content {
max-height: 200px;
}
.accordion-body {
padding: 0px 20px 16px;
color: rgba(255, 255, 255, 0.6);
font-size: 0.9rem;
line-height: 1.6;
}
.accordion-single .accordion-item {
border: 1px solid rgba(99, 102, 241, 0.2);
}
.accordion-single .accordion-item.active {
border-color: rgba(99, 102, 241, 0.5);
box-shadow: rgba(99, 102, 241, 0.15) 0px 4px 20px;
}
.modal-overlay.active {
opacity: 1;
visibility: visible;
}
.modal.active {
transform: translateX(-50%) translateY(0px);
}
.customizer-toggle.active {
transform: rotate(180deg);
}
.customizer-overlay.active {
opacity: 1;
visibility: visible;
}
.customizer-panel.active {
right: 0px;
}
.bg-option.active {
border-color: var(--primary, #6366f1);
box-shadow: rgba(99, 102, 241, 0.3) 0px 0px 0px 2px;
}
.font-option.active {
background: rgba(99, 102, 241, 0.1);
border-color: var(--primary, #6366f1);
}
.option-btn.active {
background: rgba(99, 102, 241, 0.15);
border-color: var(--primary, #6366f1);
color: var(--primary, #6366f1);
}
.demo-card:hover .favorite-btn, .category-card:hover .favorite-btn, .favorite-btn.active {
opacity: 1;
}
.favorite-btn.active {
color: rgb(251, 191, 36);
}
.code-panel-overlay.active {
opacity: 1;
visibility: visible;
}
.code-panel.active {
opacity: 1;
visibility: visible;
transform: translate(-50%, -50%) scale(1);
}
.code-tab.active {
color: rgb(167, 139, 250);
background: rgba(167, 139, 250, 0.1);
}
.code-tab.active::after {
content: "";
position: absolute;
bottom: 0px;
left: 0px;
right: 0px;
height: 2px;
background: rgb(167, 139, 250);
}
.code-editor.active {
display: flex;
flex-direction: column;
}
function toggleAccordion(header, type) {
const item = header.parentElement;
const accordion = item.parentElement;
if (type === 'single') {
// Close all other items in single mode
accordion.querySelectorAll('.accordion-item').forEach(otherItem => {
if (otherItem !== item) {
otherItem.classList.remove('active');
}
});
}
item.classList.toggle('active');
}
Personnaliser
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
| type dans toggleAccordion(this, type) | 'basic' | Passer 'single' pour n'autoriser qu'une section ouverte à la fois ; 'basic' permet l'ouverture multiple simultanée. |
| .accordion-item.active .accordion-content { max-height } | 200px | Hauteur maximale dépliée. Augmentez si votre contenu dépasse 200 px (blocs de code, formulaires longs). |
| .accordion-content { transition: max-height } | 0.4s | Durée de l'animation d'ouverture/fermeture. 0.25s = vif, 0.6s = languissant. |
| .accordion-icon { transition: transform } | 0.3s | Durée de rotation du chevron — ajustez en cohérence avec la transition de contenu. |
| .accordion-item { background } | rgba(255,255,255,0.05) | Fond de chaque section. Remplacez par une couleur brand ou transparent pour un accordéon sans fond. |
| classe .accordion-single sur .accordion | absent | Active le variant bordure indigo + lueur sur l'item actif. Aucun JS requis, uniquement un attribut HTML. |
| classe .active sur .accordion-item au chargement | premier item | Pré-ouvre l'item marqué dès le rendu initial — retirez-la de tous les items pour démarrer entièrement replié. |
FAQ
Pourquoi l'animation s'arrête-t-elle avant la fin du contenu ?
La max-height est fixée à 200px dans le CSS. Si votre contenu dépasse cette valeur, la section s'ouvre jusqu'à 200 px puis coupe le reste. Augmentez max-height sur .accordion-item.active .accordion-content à la hauteur réelle de votre contenu le plus long.
Peut-on avoir plusieurs accordéons indépendants sur la même page ?
Oui. La fonction toggleAccordion remonte via parentElement jusqu'à l'accordéon parent direct — chaque .accordion est isolé. Plusieurs instances coexistent sans conflit, même avec des modes différents ('basic' et 'single' mélangés sur la même page).
L'effet respecte-t-il prefers-reduced-motion ?
Non, pas dans la version de base. Les transitions CSS s'exécutent quelle que soit la préférence système. Pour y remédier, ajoutez : @media (prefers-reduced-motion: reduce) { .accordion-content, .accordion-icon { transition: none; } }