Navigation✨ Premium

Accordion Single

Only one panel open at a time — clicking a header automatically closes the active one. Pure CSS + vanilla JS exclusive behaviour, zero dependency.

CSSJSExclusive

You'll get access to the interactive demo with a free account.

This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Navigation has 36 effects, including 4 free. Explore the category →

3 usage examples

Help centre — FAQ in a narrow side panel — Accordion Single example 1

① Help centre — FAQ in a narrow side panel

WhenA support drawer or side panel that opens in-page without navigation — constrained width, under 320 px.
WhyExclusivity keeps only one answer visible at a time, preventing excessive scroll in a narrow surface. The smooth animation guides the eye without cognitive overload.
Settings`--primary: #0ea5e9`, `max-width: 300px`, `.accordion-item.active .accordion-content max-height: 240px`, header padding reduced to `12px 16px`.
Onboarding tunnel — Step-by-step checklist — Accordion Single example 2

② Onboarding tunnel — Step-by-step checklist

WhenA 3-step sign-up wizard (Account → Profile → Payment) where each accordion block holds its own instructions — the user only sees what matters right now.
WhySingle-accordion exclusivity avoids overwhelming new users: one instruction panel at a time builds momentum and reduces drop-off at launch.
Settings`--primary: #f59e0b`, `max-width: 440px`, `.accordion-item.active .accordion-content max-height: 200px`, `transition max-height .4s` for a smooth inter-step reveal.
Account settings — Preference category sections — Accordion Single example 3

③ Account settings — Preference category sections

WhenA preferences panel (Profile, Notifications, Security) inside a dashboard — constrained page height, several categories to display without scroll.
WhyKeeping only one section expanded reduces cognitive load and clearly signals where the user is working.
Settings`--primary: #8b5cf6`, `max-width: 480px`, `.accordion-item { background: rgba(255,255,255,.03) }` for a more subtle dark-theme background.

How it works

The exclusive toggle relies on toggleAccordion(btn, mode), called via onclick on each header button. It walks the DOM two levels up: btn.parentElement gives the current .accordion-item, another .parentElement gives the .accordion container. When mode === 'single', it strips active from every sibling .accordion-item before toggling (classList.toggle) the class on the clicked item.

Opening and closing are entirely CSS-driven: the content panel (.accordion-content) starts at max-height: 0; overflow: hidden. When the parent item holds the active class, .accordion-item.active .accordion-content sets max-height to 200px. The max-height .4s transition animates the reveal — even if the actual content is shorter, the animation stays smooth.

The SVG chevron (.accordion-icon) rotates 180° via transform: rotate(180deg) on .accordion-item.active .accordion-icon, driven by a transform .3s transition. The active item also gets a stronger indigo border (rgba(99,102,241,.5)) and a diffuse box-shadow — extra visual cues without a fill-color change.

The DOM traversal (parentElement) enforces group isolation: each .accordion-single container is self-contained. Multiple accordions on the same page operate independently, sharing no state or identifier.

Accessibility

  • prefers-reduced-motion absent — the max-height .4s transition and chevron rotation fire regardless of OS preference. For WCAG 2.3 compliance add: @media (prefers-reduced-motion: reduce) { .accordion-content, .accordion-icon { transition: none; } }.
  • Buttons are native <button> elements, keyboard-navigable (Tab · Enter · Space) with no extra code.
  • No aria-expanded on buttons — a screen reader will not announce open/closed state. Add it inside toggleAccordion: btn.setAttribute('aria-expanded', c.classList.contains('active')).
  • Contrast: header text (white on ~#0a0a0f) > 10:1 — WCAG AAA. Body text at rgba(255,255,255,.6): ratio ~4.9:1 — WCAG AA.
  • No role="region" or aria-labelledby on .accordion-content panels — the button/panel association is not explicit for assistive technology.

Browser compatibility

Requires classList and CSS transitions — supported in all modern browsers. Zero external dependencies.

Chrome 80+✓ Full
Firefox 75+✓ Full
Safari 14+✓ Full
Edge 80+✓ Full
Mobile iOS✓ Full
Android Chrome✓ Full

Without JS, panels remain in their HTML-initial state (the first carries <code>class="accordion-item active"</code>). The CSS still renders the open state correctly — content stays accessible.

The code

HTML structure to paste into your page (CSS + JS available with a premium account):

index.html — structure
<div class="accordion accordion-single">
  <div class="accordion-item active">
    <button class="accordion-header" onclick="toggleAccordion(this, 'single')">
      Section title
      <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">Section content.</div>
    </div>
  </div>
  <!-- Repeat .accordion-item for each additional entry -->
</div>
🔒 Unlock the full code — from €2.99 the first month

Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
--primary #6366f1 Color of the active border and glow (rgba(--primary,.2/.5)). Swap for your brand color — border and box-shadow adapt automatically.
--text-primary #ffffff Text color for section headers. Change for a light theme or a custom palette.
.accordion max-width 350px Maximum width of the accordion container. Set to 480px for desktop layouts or 100% for a fluid container.
.accordion-item.active .accordion-content max-height 200px Maximum height of the open panel. Increase for longer content — 400px for long text, 1000px for dynamic unknown-length content.
transition: max-height .4s (.accordion-content) .4s Open/close animation duration. Reduce to .25s for more responsiveness, increase to .6s for a fuller feel.
transition: transform .3s (.accordion-icon) .3s Chevron SVG rotation duration. Align with the max-height duration for a consistent animation.
mode 'single' vs other 'single' Second argument of onclick="toggleAccordion(this, 'single')". Any value other than 'single' disables the exclusive behaviour and allows multiple panels open simultaneously.
.accordion-header padding 16px 20px Inner padding of header buttons. Reduce to 12px 16px for a dense UI, increase to 20px 24px for an airy layout.

FAQ

Yes — replace 'single' with any other value in each button's onclick attribute (e.g. toggleAccordion(this, 'multi')). In single mode the function strips active from siblings first; with another value it skips that step and allows multiple panels open.
The limit is the CSS property max-height: 200px on .accordion-item.active .accordion-content. Set it to a large value (e.g. 1000px) — the transition always animates from 0 to the target value; the visual feel stays smooth even when content is much shorter.
No. toggleAccordion walks up the DOM from the clicked button (btn → .accordion-item → .accordion) and closes only siblings within the same container. Two distinct .accordion-single groups on the page are fully independent, sharing no state or identifier.