Accordion
A Tailwind CSS accordion component for organizing content into collapsible sections.
<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.
<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.
<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.
<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.
<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:
.accordion- Container that groups accordion items.accordion-item- Individual collapsible section.accordion-trigger- Button that toggles the section.accordion-panel- Panel wrapper that controls visibility and animations.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
| Key | Action |
|---|---|
Enter / Space | Opens/closes the panel when trigger is focused |
ArrowDown | Move focus to next trigger |
ArrowUp | Move focus to previous trigger |
Home | Move focus to first trigger |
End | Move focus to last trigger |
Tab | Move focus to next/previous focusable element |
Class reference
| Class | Description |
|---|---|
accordion | Container that groups accordion items |
accordion-item | Individual collapsible section |
accordion-trigger | Button that toggles the section |
accordion-trigger-icon-arrow | Chevron icon that rotates (default) |
accordion-trigger-icon-plus | Plus/minus icon |
accordion-trigger-icon-none | Hide the icon |
accordion-trigger-icon-start | Position icon before the text |
accordion-trigger-icon-end | Position icon after the text (default) |
accordion-panel | Panel wrapper that controls visibility and animations |
accordion-content | Content container with padding and text styles |
open | Add to .accordion-panel to show by default |
no-animation | Add to .accordion-panel to disable animations |
Data attributes
| Attribute | Description |
|---|---|
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-multiple | Add to .accordion to allow multiple panels open at once |
data-state | Set on .accordion-panel to open or closed during animation |