Accordion

A Tailwind CSS accordion component for organizing content into collapsible sections.

Yes. It adheres to the WAI-ARIA design pattern for accordions.
Yes. It comes with default styles that match your theme.
Yes. It's animated using CSS animations.
<div class="accordion max-w-lg">
  <div class="accordion-item">
    <button
      class="accordion-trigger"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#accordion-panel-1"
      aria-expanded="true"
      aria-controls="accordion-panel-1"
    >
      Is it accessible?
    </button>
    <div id="accordion-panel-1" class="accordion-panel open">
      <div class="accordion-content">
        Yes. It adheres to the WAI-ARIA design pattern for accordions.
      </div>
    </div>
  </div>
  <div class="accordion-item">
    <button
      class="accordion-trigger"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#accordion-panel-2"
      aria-expanded="false"
      aria-controls="accordion-panel-2"
    >
      Is it styled?
    </button>
    <div id="accordion-panel-2" class="accordion-panel">
      <div class="accordion-content">
        Yes. It comes with default styles that match your theme.
      </div>
    </div>
  </div>
  <div class="accordion-item">
    <button
      class="accordion-trigger"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#accordion-panel-3"
      aria-expanded="false"
      aria-controls="accordion-panel-3"
    >
      Is it animated?
    </button>
    <div id="accordion-panel-3" class="accordion-panel">
      <div class="accordion-content">
        Yes. It's animated using CSS animations.
      </div>
    </div>
  </div>
</div>

Multiple open

Add data-sp-multiple to the accordion to allow multiple sections to be open at the same time.

This accordion allows multiple sections to be open at once.
Both sections can be expanded simultaneously.
<div class="accordion max-w-lg" data-sp-multiple>
  <div class="accordion-item">
    <button
      class="accordion-trigger"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#multi-panel-1"
      aria-expanded="true"
      aria-controls="multi-panel-1"
    >
      First section
    </button>
    <div id="multi-panel-1" class="accordion-panel open">
      <div class="accordion-content">
        This accordion allows multiple sections to be open at once.
      </div>
    </div>
  </div>
  <div class="accordion-item">
    <button
      class="accordion-trigger"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#multi-panel-2"
      aria-expanded="true"
      aria-controls="multi-panel-2"
    >
      Second section
    </button>
    <div id="multi-panel-2" class="accordion-panel open">
      <div class="accordion-content">
        Both sections can be expanded simultaneously.
      </div>
    </div>
  </div>
</div>

Plus/minus icon

Add accordion-trigger-icon-plus to use plus/minus icons instead of the chevron.

This section shows the minus icon when expanded.
This section shows the plus icon when collapsed.
<div class="accordion max-w-lg">
  <div class="accordion-item">
    <button
      class="accordion-trigger accordion-trigger-icon-plus"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#plus-panel-1"
      aria-expanded="true"
      aria-controls="plus-panel-1"
    >
      Expanded section
    </button>
    <div id="plus-panel-1" class="accordion-panel open">
      <div class="accordion-content">
        This section shows the minus icon when expanded.
      </div>
    </div>
  </div>
  <div class="accordion-item">
    <button
      class="accordion-trigger accordion-trigger-icon-plus"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#plus-panel-2"
      aria-expanded="false"
      aria-controls="plus-panel-2"
    >
      Collapsed section
    </button>
    <div id="plus-panel-2" class="accordion-panel">
      <div class="accordion-content">
        This section shows the plus icon when collapsed.
      </div>
    </div>
  </div>
</div>

Icon position

Add accordion-trigger-icon-start to position the icon before the text. This can be combined with accordion-trigger-icon-plus.

The icon appears before the text.
Combining both modifiers.
<div class="accordion max-w-lg">
  <div class="accordion-item">
    <button
      class="accordion-trigger accordion-trigger-icon-start"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#start-panel-1"
      aria-expanded="true"
      aria-controls="start-panel-1"
    >
      Chevron at start
    </button>
    <div id="start-panel-1" class="accordion-panel open">
      <div class="accordion-content">The icon appears before the text.</div>
    </div>
  </div>
  <div class="accordion-item">
    <button
      class="accordion-trigger accordion-trigger-icon-start accordion-trigger-icon-plus"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#start-panel-2"
      aria-expanded="false"
      aria-controls="start-panel-2"
    >
      Plus/minus at start
    </button>
    <div id="start-panel-2" class="accordion-panel">
      <div class="accordion-content">Combining both modifiers.</div>
    </div>
  </div>
</div>

Disabled

Add disabled to the trigger button to prevent interaction.

This section can be toggled.
This section cannot be opened.
This section can also be toggled.
<div class="accordion max-w-lg">
  <div class="accordion-item">
    <button
      class="accordion-trigger"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#disabled-panel-1"
      aria-expanded="true"
      aria-controls="disabled-panel-1"
    >
      Enabled section
    </button>
    <div id="disabled-panel-1" class="accordion-panel open">
      <div class="accordion-content">This section can be toggled.</div>
    </div>
  </div>
  <div class="accordion-item">
    <button
      class="accordion-trigger"
      type="button"
      disabled
      data-sp-toggle="accordion"
      data-sp-target="#disabled-panel-2"
      aria-expanded="false"
      aria-controls="disabled-panel-2"
    >
      Disabled section
    </button>
    <div id="disabled-panel-2" class="accordion-panel">
      <div class="accordion-content">This section cannot be opened.</div>
    </div>
  </div>
  <div class="accordion-item">
    <button
      class="accordion-trigger"
      type="button"
      data-sp-toggle="accordion"
      data-sp-target="#disabled-panel-3"
      aria-expanded="false"
      aria-controls="disabled-panel-3"
    >
      Another enabled section
    </button>
    <div id="disabled-panel-3" class="accordion-panel">
      <div class="accordion-content">This section can also be toggled.</div>
    </div>
  </div>
</div>

How it works

The accordion component uses a small JavaScript module that handles opening and closing content panels. By default, only one section can be open at a time.

Structure

An accordion consists of five parts:

  1. .accordion - Container that groups accordion items
  2. .accordion-item - Individual collapsible section
  3. .accordion-trigger - Button that toggles the section
  4. .accordion-panel - Panel wrapper that controls visibility and animations
  5. .accordion-content - Content container with padding and text styles
<div class="accordion">
  <div class="accordion-item">
    <button
      class="accordion-trigger"
      data-sp-toggle="accordion"
      data-sp-target="#panel-1"
    >
      Section title
    </button>
    <div id="panel-1" class="accordion-panel">
      <div class="accordion-content">Section content</div>
    </div>
  </div>
</div>

Opening and closing

Use data attributes to control the accordion without writing JavaScript.

Add data-sp-toggle="accordion" to the trigger button and data-sp-target to specify which panel to toggle:

<button data-sp-toggle="accordion" data-sp-target="#panel-1">Toggle</button>

By default, opening a panel will close any other open panels in the same accordion. Add data-sp-multiple to the .accordion container to allow multiple panels open at once.

For programmatic control, use the global sp.accordion module:

const panel = document.querySelector("#panel-1");
 
sp.accordion.open(panel);
sp.accordion.close(panel);
sp.accordion.toggle(panel);

Animation

The accordion includes a smooth height animation using CSS keyframes.

To disable animations, add no-animation to the panel:

<div class="accordion-panel no-animation">...</div>

Accessibility

For proper accessibility, add aria-expanded and aria-controls to the trigger button:

<button
  data-sp-toggle="accordion"
  data-sp-target="#panel-1"
  aria-expanded="false"
  aria-controls="panel-1"
>
  Toggle
</button>

The JavaScript will automatically update aria-expanded when the panel opens and closes.

Keyboard navigation

KeyAction
Enter / SpaceOpens/closes the panel when trigger is focused
ArrowDownMove focus to next trigger
ArrowUpMove focus to previous trigger
HomeMove focus to first trigger
EndMove focus to last trigger
TabMove focus to next/previous focusable element

Class reference

ClassDescription
accordionContainer that groups accordion items
accordion-itemIndividual collapsible section
accordion-triggerButton that toggles the section
accordion-trigger-icon-arrowChevron icon that rotates (default)
accordion-trigger-icon-plusPlus/minus icon
accordion-trigger-icon-noneHide the icon
accordion-trigger-icon-startPosition icon before the text
accordion-trigger-icon-endPosition icon after the text (default)
accordion-panelPanel wrapper that controls visibility and animations
accordion-contentContent container with padding and text styles
openAdd to .accordion-panel to show by default
no-animationAdd to .accordion-panel to disable animations

Data attributes

AttributeDescription
data-sp-toggle="accordion"Add to trigger button to toggle the accordion panel
data-sp-target="#id"Add to trigger button to specify which panel to toggle
data-sp-multipleAdd to .accordion to allow multiple panels open at once
data-stateSet on .accordion-panel to open or closed during animation