Accordions
Accordions expand and collapse content sections, helping users focus on relevant information without overwhelming the page. Built on native <details> and <summary> elements for optimal accessibility.
Installation
Copy the accordion CSS from styles/docs.css or include the Standard stylesheet:
<link rel="stylesheet" href="standard.min.css">
Then use accordion classes in your HTML:
<div class="Accordion">
<details class="Accordion-item">
<summary class="Accordion-header">Section Title</summary>
<div class="Accordion-content">
<p>Content goes here...</p>
</div>
</details>
</div>
Usage
The base .Accordion class provides the container styling. Each panel uses native <details> and <summary> elements for built-in accessibility and keyboard support.
What is Standard?
Standard is a framework-agnostic design system built with OKLCH colors and a 4px spacing scale.
How do I install it?
Simply include the CSS file in your project. No JavaScript framework required.
Is it accessible?
Yes! Native elements provide built-in keyboard navigation and screen reader support.
<div class="Accordion">
<details class="Accordion-item">
<summary class="Accordion-header">What is Standard?</summary>
<div class="Accordion-content">
<p>Standard is a framework-agnostic design system built with OKLCH colors and a 4px spacing scale.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">How do I install it?</summary>
<div class="Accordion-content">
<p>Simply include the CSS file in your project. No JavaScript framework required.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">Is it accessible?</summary>
<div class="Accordion-content">
<p>Yes! Native elements provide built-in keyboard navigation and screen reader support.</p>
</div>
</details>
</div>
Examples
With Icons
Add chevron indicators that rotate on expand using the .Accordion--icons modifier and .Accordion-icon class.
<div class="Accordion Accordion--icons">
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Account Settings</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Manage your account preferences, email notifications, and security settings.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Privacy & Security</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Control who can see your profile and manage two-factor authentication.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Billing Information</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Update your payment method, view invoices, and manage your subscription.</p>
</div>
</details>
</div>
Bordered
Add visible borders between items with the .Accordion--bordered modifier.
Getting Started
Learn the basics of using Standard in your projects.
Components
Explore the full library of UI components.
Customization
Learn how to customize tokens and extend the system.
<div class="Accordion Accordion--bordered">
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Getting Started</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Learn the basics of using Standard in your projects.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Components</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Explore the full library of UI components.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Customization</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Learn how to customize tokens and extend the system.</p>
</div>
</details>
</div>
Flush
No outer borders for seamless integration into cards or panels.
Order Summary
Shipping Address
123 Main Street
San Francisco, CA 94102
<div style="background: var(--bg-s); padding: var(--space-4); border-radius: var(--r-m);">
<div class="Accordion Accordion--flush">
<details class="Accordion-item" open>
<summary class="Accordion-header">
<span>Order Summary</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<div class="Layout-split" style="margin-bottom: var(--space-2);">
<span>Subtotal</span>
<span>$99.00</span>
</div>
<div class="Layout-split" style="margin-bottom: var(--space-2);">
<span>Shipping</span>
<span>$5.00</span>
</div>
<div class="Layout-split" style="font-weight: 600;">
<span>Total</span>
<span>$104.00</span>
</div>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Shipping Address</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>123 Main Street<br>San Francisco, CA 94102</p>
</div>
</details>
</div>
</div>
Default Open
Use the open attribute to expand an item by default.
This section is open by default
Add the open attribute to the <details> element to have it expanded on page load.
This section is closed
Click to expand this content.
<div class="Accordion Accordion--bordered">
<details class="Accordion-item" open>
<summary class="Accordion-header">
<span>This section is open by default</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Add the <code>open</code> attribute to the <code><details></code> element to have it expanded on page load.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<span>This section is closed</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Click to expand this content.</p>
</div>
</details>
</div>
Single Expand (Exclusive)
Use JavaScript to ensure only one item is open at a time. Add data-accordion="exclusive" to enable this behavior.
Panel One
When this opens, other panels close automatically.
Panel Two
Only one panel can be open at a time.
Panel Three
This creates a traditional accordion behavior.
<div class="Accordion Accordion--bordered" data-accordion="exclusive">
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Panel One</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>When this opens, other panels close automatically.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Panel Two</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Only one panel can be open at a time.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Panel Three</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>This creates a traditional accordion behavior.</p>
</div>
</details>
</div>
// Exclusive accordion behavior
document.querySelectorAll('[data-accordion="exclusive"]').forEach(accordion => {
accordion.querySelectorAll('details').forEach(details => {
details.addEventListener('toggle', () => {
if (details.open) {
accordion.querySelectorAll('details').forEach(other => {
if (other !== details) other.open = false;
});
}
});
});
});
With Rich Content
Accordions can contain any content, including other components.
Team Members
<div class="Accordion Accordion--bordered">
<details class="Accordion-item" open>
<summary class="Accordion-header">
<span>Team Members</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<div class="Layout-stack Layout-stack--tight">
<div class="Layout-split">
<div style="display: flex; align-items: center; gap: var(--space-3);">
<div class="Avatar" style="background: var(--accent); color: white; display: flex; align-items: center; justify-content: center; font-weight: 600;">A</div>
<div>
<div style="font-weight: 500;">Alice Johnson</div>
<div style="font-size: 0.85rem; color: var(--fg-3);">Design Lead</div>
</div>
</div>
<span class="Badge Badge--success">Active</span>
</div>
<div class="Layout-split">
<div style="display: flex; align-items: center; gap: var(--space-3);">
<div class="Avatar" style="background: oklch(55% 0.15 150); color: white; display: flex; align-items: center; justify-content: center; font-weight: 600;">B</div>
<div>
<div style="font-weight: 500;">Bob Smith</div>
<div style="font-size: 0.85rem; color: var(--fg-3);">Developer</div>
</div>
</div>
<span class="Badge Badge--success">Active</span>
</div>
</div>
</div>
</details>
</div>
Common Patterns
FAQ Section
Frequently Asked Questions
What payment methods do you accept?
We accept Visa, Mastercard, American Express, and PayPal. All transactions are encrypted and secure.
How do I cancel my subscription?
Go to Settings → Billing → Cancel Subscription. Your access continues until the end of the billing period.
Do you offer refunds?
Yes, we offer a 30-day money-back guarantee for all plans. Contact support to request a refund.
<div style="max-width: 600px;">
<h3 style="margin: 0 0 var(--space-4); font-size: 1.25rem;">Frequently Asked Questions</h3>
<div class="Accordion Accordion--bordered">
<details class="Accordion-item">
<summary class="Accordion-header">
<span>What payment methods do you accept?</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>We accept Visa, Mastercard, American Express, and PayPal. All transactions are encrypted and secure.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<span>How do I cancel my subscription?</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Go to Settings → Billing → Cancel Subscription. Your access continues until the end of the billing period.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<span>Do you offer refunds?</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p>Yes, we offer a 30-day money-back guarantee for all plans. Contact support to request a refund.</p>
</div>
</details>
</div>
</div>
Settings Panel
Profile Settings
Manage your display name, bio, and profile picture.
Notifications
Configure email, push, and in-app notification preferences.
Security
Two-factor authentication, password changes, and active sessions.
<div style="max-width: 480px; background: var(--bg-s); padding: var(--space-4); border-radius: var(--r-m);">
<div class="Accordion Accordion--flush">
<details class="Accordion-item" open>
<summary class="Accordion-header">
<div style="display: flex; align-items: center; gap: var(--space-2);">
<i class="ph ph-user" style="font-size: 1.1rem;"></i>
<span>Profile Settings</span>
</div>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p style="color: var(--fg-3); font-size: 0.875rem;">Manage your display name, bio, and profile picture.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<div style="display: flex; align-items: center; gap: var(--space-2);">
<i class="ph ph-bell" style="font-size: 1.1rem;"></i>
<span>Notifications</span>
</div>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p style="color: var(--fg-3); font-size: 0.875rem;">Configure email, push, and in-app notification preferences.</p>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header">
<div style="display: flex; align-items: center; gap: var(--space-2);">
<i class="ph ph-shield-check" style="font-size: 1.1rem;"></i>
<span>Security</span>
</div>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content">
<p style="color: var(--fg-3); font-size: 0.875rem;">Two-factor authentication, password changes, and active sessions.</p>
</div>
</details>
</div>
</div>
Sidebar Filter
<div style="max-width: 260px; border: 1px solid var(--bd); border-radius: var(--r-m); padding: var(--space-3);">
<div class="Accordion Accordion--flush Accordion--icons">
<details class="Accordion-item" open>
<summary class="Accordion-header" style="font-size: 0.875rem; font-weight: 600;">
<span>Category</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content" style="font-size: 0.85rem;">
<label style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2);"><input type="checkbox" checked> Electronics</label>
<label style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2);"><input type="checkbox"> Clothing</label>
<label style="display: flex; align-items: center; gap: var(--space-2);"><input type="checkbox"> Books</label>
</div>
</details>
<details class="Accordion-item">
<summary class="Accordion-header" style="font-size: 0.875rem; font-weight: 600;">
<span>Price Range</span>
<i class="ph ph-caret-down Accordion-icon"></i>
</summary>
<div class="Accordion-content" style="font-size: 0.85rem;">
<label style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2);"><input type="radio" name="price"> Under $25</label>
<label style="display: flex; align-items: center; gap: var(--space-2); margin-bottom: var(--space-2);"><input type="radio" name="price"> $25 – $100</label>
<label style="display: flex; align-items: center; gap: var(--space-2);"><input type="radio" name="price"> Over $100</label>
</div>
</details>
</div>
</div>
Customization
Override accordion styles using CSS custom properties:
/* Custom header styling */
.Accordion-header {
--accordion-padding: var(--space-4);
--accordion-bg-hover: var(--bg-tertiary);
padding: var(--accordion-padding);
}
.Accordion-header:hover {
background-color: var(--accordion-bg-hover);
}
/* Custom border color */
.Accordion--bordered {
--accordion-border: var(--border-default);
border-color: var(--accordion-border);
}
/* Custom icon animation */
.Accordion-icon {
--accordion-icon-rotation: 180deg;
transition: transform 0.3s ease;
}
details[open] .Accordion-icon {
transform: rotate(var(--accordion-icon-rotation));
}
/* Compact accordion */
.Accordion--compact .Accordion-header {
padding: var(--space-2) var(--space-3);
font-size: 0.875rem;
}
.Accordion--compact .Accordion-content {
padding: 0 var(--space-3) var(--space-3);
font-size: 0.875rem;
}
API Reference
Container Classes
| Class | Description |
|---|---|
.Accordion |
Base accordion container (required) |
.Accordion--icons |
Enables icon rotation animation |
.Accordion--bordered |
Adds borders around accordion and between items |
.Accordion--flush |
Removes horizontal padding for card integration |
Item Classes
| Class | Description |
|---|---|
.Accordion-item |
Wrapper for each accordion panel (use on <details>) |
.Accordion-header |
Clickable header element (use on <summary>) |
.Accordion-content |
Collapsible content container |
.Accordion-icon |
Chevron icon that rotates on expand |
Data Attributes
| Attribute | Value | Description |
|---|---|---|
data-accordion |
"exclusive" |
Only one panel can be open at a time (requires JS) |
open |
boolean | Native attribute to expand panel by default |
CSS Reference
/* Base Accordion */
.Accordion {
width: 100%;
}
.Accordion-item {
border: none;
}
.Accordion-item + .Accordion-item {
border-top: 1px solid var(--bd);
}
.Accordion-header {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: var(--space-3) var(--space-4);
background: none;
border: none;
cursor: pointer;
font-weight: 500;
font-size: 0.9375rem;
color: var(--fg);
list-style: none;
transition: background-color 0.15s;
}
.Accordion-header::-webkit-details-marker {
display: none;
}
.Accordion-header::marker {
display: none;
content: "";
}
.Accordion-header:hover {
background-color: var(--bg-s);
}
.Accordion-header:focus-visible {
outline: 2px solid var(--accent);
outline-offset: -2px;
}
.Accordion-content {
padding: 0 var(--space-4) var(--space-4);
color: var(--fg-3);
font-size: 0.875rem;
line-height: 1.6;
}
/* Icon rotation */
.Accordion-icon {
font-size: 1rem;
color: var(--fg-3);
transition: transform 0.2s ease;
flex-shrink: 0;
}
details[open] > .Accordion-header .Accordion-icon {
transform: rotate(180deg);
}
/* Bordered variant */
.Accordion--bordered {
border: 1px solid var(--bd);
border-radius: var(--r-m);
overflow: hidden;
}
.Accordion--bordered .Accordion-item + .Accordion-item {
border-top: 1px solid var(--bd);
}
/* Flush variant */
.Accordion--flush .Accordion-header {
padding-left: 0;
padding-right: 0;
}
.Accordion--flush .Accordion-content {
padding-left: 0;
padding-right: 0;
}
.Accordion--flush .Accordion-item:first-child .Accordion-header {
padding-top: 0;
}
Accessibility
Keyboard Support
| Key | Action |
|---|---|
| Enter | Toggles the focused accordion panel |
| Space | Toggles the focused accordion panel |
| Tab | Moves focus to the next focusable element |
| Shift + Tab | Moves focus to the previous focusable element |
Screen Readers
Native <details> and <summary> elements provide excellent accessibility:
<!-- Native accordion — fully accessible out of the box -->
<details class="Accordion-item">
<summary class="Accordion-header">Section Title</summary>
<div class="Accordion-content">
<p>Content is announced when expanded.</p>
</div>
</details>
<!-- Default expanded state -->
<details class="Accordion-item" open>
<summary class="Accordion-header">Open Section</summary>
<div class="Accordion-content">
<p>Screen readers announce "expanded" state.</p>
</div>
</details>
Custom Implementation
For non-native implementations, use proper ARIA attributes:
<div class="Accordion">
<div class="Accordion-item">
<button id="accordion-header-1"
class="Accordion-header"
aria-expanded="false"
aria-controls="accordion-panel-1">
Section Title
</button>
<div id="accordion-panel-1"
class="Accordion-content"
role="region"
aria-labelledby="accordion-header-1"
hidden>
<p>Content...</p>
</div>
</div>
</div>
Best Practices
Do
- ✓ Use clear, descriptive headers — Users decide to expand based on the title
- ✓ Keep content focused — Each section should cover one topic
- ✓ Consider default states — Open the most important section by default
- ✓ Use native elements —
<details>and<summary>provide built-in accessibility - ✓ Use for optional content — Hide supplementary info, not critical content
Don’t
- ✗ Hide primary content — Don’t make users hunt for important information
- ✗ Nest accordions deeply — One level is usually enough
- ✗ Use for very short content — If it fits easily, just show it
- ✗ Override keyboard behavior — Let native elements handle interaction
- ✗ Forget visual indicators — Use icons to show expand/collapse state