← Catalogue

FAQ Accordion

Accordéon FAQ : un seul item ouvert à la fois, toggle +/- animé et réponse à hauteur animée.

#faq#accordéon#toggle#disclosure

Aperçu

FAQ Accordion

Code source

HTML
<div class="wtl-faq">
<div class="wtl-faq__item">
<button class="wtl-faq__q" type="button" aria-expanded="false">
<span class="wtl-faq__question">Comment fonctionne le service&nbsp;?</span>
<span class="wtl-faq__toggle" aria-hidden="true">
<span class="wtl-faq__bar wtl-faq__bar--h"></span>
<span class="wtl-faq__bar wtl-faq__bar--v"></span>
</span>
</button>
<div class="wtl-faq__answer">
<div class="wtl-faq__answer-inner">
On définit ensemble vos besoins, puis on met en place la solution adaptée et on en assure le suivi. Vous gardez la main, on s'occupe du reste.
</div>
</div>
</div>
<div class="wtl-faq__item">
<button class="wtl-faq__q" type="button" aria-expanded="false">
<span class="wtl-faq__question">Combien ça coûte&nbsp;?</span>
<span class="wtl-faq__toggle" aria-hidden="true">
<span class="wtl-faq__bar wtl-faq__bar--h"></span>
<span class="wtl-faq__bar wtl-faq__bar--v"></span>
</span>
</button>
<div class="wtl-faq__answer">
<div class="wtl-faq__answer-inner">
Le tarif dépend de votre projet et du niveau d'accompagnement souhaité. Contactez-nous pour une estimation personnalisée, sans engagement.
</div>
</div>
</div>
<div class="wtl-faq__item">
<button class="wtl-faq__q" type="button" aria-expanded="false">
<span class="wtl-faq__question">Puis-je annuler à tout moment&nbsp;?</span>
<span class="wtl-faq__toggle" aria-hidden="true">
<span class="wtl-faq__bar wtl-faq__bar--h"></span>
<span class="wtl-faq__bar wtl-faq__bar--v"></span>
</span>
</button>
<div class="wtl-faq__answer">
<div class="wtl-faq__answer-inner">
Oui. Aucune durée minimale imposée : vous restez libre d'ajuster ou d'arrêter quand vous le souhaitez.
</div>
</div>
</div>
<div class="wtl-faq__item">
<button class="wtl-faq__q" type="button" aria-expanded="false">
<span class="wtl-faq__question">Proposez-vous un support&nbsp;?</span>
<span class="wtl-faq__toggle" aria-hidden="true">
<span class="wtl-faq__bar wtl-faq__bar--h"></span>
<span class="wtl-faq__bar wtl-faq__bar--v"></span>
</span>
</button>
<div class="wtl-faq__answer">
<div class="wtl-faq__answer-inner">
Une équipe reste joignable pour répondre à vos questions et vous accompagner à chaque étape.
</div>
</div>
</div>
<div class="wtl-faq__item">
<button class="wtl-faq__q" type="button" aria-expanded="false">
<span class="wtl-faq__question">Mes données sont-elles sécurisées&nbsp;?</span>
<span class="wtl-faq__toggle" aria-hidden="true">
<span class="wtl-faq__bar wtl-faq__bar--h"></span>
<span class="wtl-faq__bar wtl-faq__bar--v"></span>
</span>
</button>
<div class="wtl-faq__answer">
<div class="wtl-faq__answer-inner">
Vos données sont traitées de façon confidentielle et ne sont jamais partagées sans votre accord.
</div>
</div>
</div>
</div>
CSS
/* FAQ Accordion — items en cartes, toggle +/− qui pivote, réponse à hauteur
animée (gérée en JS). Police Geist, aucune dépendance.
Un seul item ouvert à la fois. */
.wtl-faq {
--wtl-faq-bg: #f4f3f1; /* fond des items */
--wtl-faq-ink: #14110f; /* question + pastille toggle */
--wtl-faq-ink-soft: #6b6258; /* texte des réponses */
--wtl-faq-accent: #d94a26; /* toggle à l'état ouvert */
--wtl-faq-radius: 18px;
--wtl-faq-ease: cubic-bezier(0.16, 1, 0.3, 1);
width: 100%;
max-width: 820px;
margin: 0 auto;
padding: 2rem 1.5rem;
font-family: "Geist", system-ui, sans-serif;
}
.wtl-faq__item {
background: var(--wtl-faq-bg);
border-radius: var(--wtl-faq-radius);
margin-bottom: 0.85rem;
overflow: hidden;
}
.wtl-faq__q {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1.5rem;
text-align: left;
padding: 1.4rem 1.5rem;
cursor: pointer;
background: none;
border: none;
font-family: inherit;
}
.wtl-faq__question {
font-weight: 500;
font-size: 1.05rem;
line-height: 1.4;
color: var(--wtl-faq-ink);
}
.wtl-faq__toggle {
position: relative;
width: 2.25rem;
height: 2.25rem;
border-radius: 999px;
background: var(--wtl-faq-ink);
flex: none;
transition: background-color 0.35s var(--wtl-faq-ease);
}
.wtl-faq__item.is-open .wtl-faq__toggle {
background: var(--wtl-faq-accent);
}
.wtl-faq__bar {
position: absolute;
top: 50%;
left: 50%;
width: 13px;
height: 2px;
border-radius: 2px;
background: #fff;
transition:
transform 0.35s var(--wtl-faq-ease),
opacity 0.3s var(--wtl-faq-ease);
}
.wtl-faq__bar--h {
transform: translate(-50%, -50%);
}
.wtl-faq__bar--v {
transform: translate(-50%, -50%) rotate(90deg);
}
.wtl-faq__item.is-open .wtl-faq__bar--v {
transform: translate(-50%, -50%) rotate(0deg);
opacity: 0;
}
.wtl-faq__answer {
overflow: hidden;
height: 0;
transition: height 0.4s var(--wtl-faq-ease);
}
.wtl-faq__answer-inner {
padding: 0 1.5rem 1.5rem;
color: var(--wtl-faq-ink-soft);
line-height: 1.6;
}
@media (min-width: 768px) {
.wtl-faq__q {
padding: 1.6rem 1.9rem;
}
.wtl-faq__question {
font-size: 1.18rem;
}
.wtl-faq__answer-inner {
padding: 0 1.9rem 1.7rem;
}
}
JS
// Accordéon FAQ : un seul item ouvert à la fois, hauteur animée en JS (fiable).
document.querySelectorAll(".wtl-faq__item").forEach((item) => {
const answer = item.querySelector(".wtl-faq__answer");
const button = item.querySelector(".wtl-faq__q");
button.addEventListener("click", () => {
const isOpen = item.classList.contains("is-open");
// Ferme tout ce qui est ouvert.
document.querySelectorAll(".wtl-faq__item.is-open").forEach((el) => {
el.classList.remove("is-open");
el.querySelector(".wtl-faq__answer").style.height = "0px";
el.querySelector(".wtl-faq__q").setAttribute("aria-expanded", "false");
});
// Ouvre l'item cliqué s'il était fermé.
if (!isOpen) {
item.classList.add("is-open");
answer.style.height = answer.scrollHeight + "px";
button.setAttribute("aria-expanded", "true");
}
});
});