Accordion
Create accessible, responsive accordions using HTML5 native elements with Chassis CSS. Features smooth transitions, multiple styling options, and built-in accessibility without extensive JavaScript.
How It Works
Chassis accordions leverage the native HTML5 <details> and <summary> elements, providing several key benefits:
- Native browser functionality: The browser handles expanding and collapsing content without requiring extensive JavaScript
- Built-in accessibility: Native keyboard navigation and screen reader support through the HTML5 elements
- Enhanced with JavaScript: While fully functional without JavaScript, our optional JS adds smooth transitions between states
- Group behavior: Using the same
nameattribute on multiple<details>elements creates accordion groups where only one item can be open at a time
Chassis CSS respects user accessibility preferences by automatically disabling animations when the prefers-reduced-motion media query is detected. See the reduced motion guidelines in our accessibility documentation for implementation details.
Examples
Click the accordions below to expand/collapse the content. Each item in this example shares the same name="example" attribute, creating a group where only one accordion can be open at a time.
Add the open attribute to any <details> element to render it expanded by default.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
<div class="accordion">
<details name="example" open>
<summary>
<span class="accordion-title">Accordion Item #1</span>
</summary>
<div class="accordion-body">
<p>This is the <b>first item's body</b>, shown by default. It will automatically close when another item is opened by clicking its summary element.</p>
</div>
</details>
<details name="example">
<summary>
<span class="accordion-title">Accordion Item #2</span>
</summary>
<div class="accordion-body">
<p>This is the <b>second item's body</b>. It is hidden by default and will open when its summary element is clicked.</p>
</div>
</details>
<details name="example">
<summary>
<span class="accordion-title">Accordion Item #3</span>
</summary>
<div class="accordion-body">
<p>This is the <b>third item's body</b>. It is hidden by default and will open when its summary element is clicked.</p>
</div>
</details>
</div> Headings
Note that this pattern optimizes screen reader accessibility but uses ARIA role combinations that don't comply with current W3C validation standards. Chassis chooses to prioritize functional accessibility over validation conformance in this case.
Because the <summary> element has a button role by default (which overrides the roles of its child elements), heading elements inside <summary> are not recognized by assistive technologies like screen readers.
Fortunately, by swapping the ARIA roles of <summary> and heading elements and manually setting the aria-expanded attribute, you can create accessible accordions with headings using the <details> element.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
<div class="accordion">
<details name="example-headings" open>
<summary role="heading" aria-level="3">
<h3 class="accordion-title" role="button" aria-expanded="true">Accordion Item #1</h3>
</summary>
<div class="accordion-body">
<p>This is the <b>first item's body</b>, shown by default. It will automatically close when another item is opened by clicking its summary element.</p>
</div>
</details>
<details name="example-headings">
<summary role="heading" aria-level="3">
<h3 class="accordion-title" role="button" aria-expanded="false">Accordion Item #2</h3>
</summary>
<div class="accordion-body">
<p>This is the <b>second item's body</b>. It is hidden by default and will open when its summary element is clicked.</p>
</div>
</details>
<details name="example-headings">
<summary role="heading" aria-level="3">
<h3 class="accordion-title" role="button" aria-expanded="false">Accordion Item #3</h3>
</summary>
<div class="accordion-body">
<p>This is the <b>third item's body</b>. It is hidden by default and will open when its summary element is clicked.</p>
</div>
</details>
</div> Static Items
Accordions with the same name attribute form groups that close automatically when another item in the group is opened. Items without a name attribute (or with unique names) remain independent. You can mix both types in a single accordion.
Accordion Item #1
This is the first item's body, shown by default. Since it has no name attribute, it behaves independently and will only close when its own summary element is clicked.
Accordion Item #2
This item shares the example-static name attribute with Accordion Item #3, forming a group. It will automatically close when Accordion Item #3 is opened.
Accordion Item #3
This item shares the example-static name attribute with Accordion Item #2, forming a group. It will automatically close when Accordion Item #2 is opened.
<div class="accordion">
<details open>
<summary>
<span class="accordion-title">Accordion Item #1</span>
</summary>
<div class="accordion-body">
<p>This is the first item's body, shown by default. Since it has <b>no name attribute</b>, it behaves independently and will only close when its own summary element is clicked.</p>
</div>
</details>
<details name="example-static" open>
<summary>
<span class="accordion-title">Accordion Item #2</span>
</summary>
<div class="accordion-body">
<p>This item shares the <b>example-static</b> name attribute with Accordion Item #3, forming a group. It will automatically close when <b>Accordion Item #3</b> is opened.</p>
</div>
</details>
<details name="example-static">
<summary>
<span class="accordion-title">Accordion Item #3</span>
</summary>
<div class="accordion-body">
<p>This item shares the <b>example-static</b> name attribute with Accordion Item #2, forming a group. It will automatically close when <b>Accordion Item #2</b> is opened.</p>
</div>
</details>
</div> Flush Accordion
Add .flush to remove some borders and rounded corners to render accordions edge-to-edge with their parent container.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
<div class="accordion flush">
...
</div>
Indicator Position
Add .indicator-end to the accordion container to move the indicator icon to the end of the summary element.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
<div class="accordion indicator-end">
...
</div>
Disable Animation
Add .no-transition to the accordion container to disable the smooth transition effect.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
<div class="accordion no-transition">
...
</div>
Sizes
In FigmaChassis CSS offers size variations to help accordions integrate seamlessly with different UI contexts. Adjust sizes to establish visual hierarchy and optimize space utilization based on your layout requirements.
Large
Add .large for larger font size and more generous spacing. Suitable for primary content areas, FAQ sections, or hero elements where accordions need more visual prominence.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
<div class="accordion large">
...
</div>
Small
Add .small for reduced font size and compact spacing. Suitable for secondary content areas like cards, sidebars, or dense layouts where space efficiency is a priority.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
<div class="accordion small">
...
</div>
Context Variants
CSS OnlyYou can use the .context class to add a color or style to the accordion. The context class is used to apply a specific color scheme or style to the accordion, making it visually distinct and aligned with your design preferences. See context class for more information.
Colors
Use .context class on accordion with a color, like .primary.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
<div class="accordion context neutral small">
...
</div>
<div class="accordion context primary small">
...
</div>
<div class="accordion context secondary small">
...
</div>
<div class="accordion context alternate small">
...
</div>
Styles
Use .context class on accordions with a color and style, like .primary and .solid.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #1
This is the first item's body, shown by default. It will automatically close when another item is opened by clicking its summary element.
Accordion Item #2
This is the second item's body. It is hidden by default and will open when its summary element is clicked.
Accordion Item #3
This is the third item's body. It is hidden by default and will open when its summary element is clicked.
<div class="accordion context primary small">
...
</div>
<div class="accordion context primary solid small">
...
</div>
<div class="accordion context primary smooth small">
...
</div>
<div class="accordion context primary outline small">
...
</div>
Accessibility
The accordion component leverages the native HTML5 <details> and <summary> elements, which provide built-in accessibility features including keyboard navigation, focus management, and appropriate ARIA states without additional JavaScript. This ensures users of assistive technologies can interact with accordions using standard navigation patterns.
Using Headings
Note that this pattern optimizes screen reader accessibility but uses ARIA role combinations that don't comply with current W3C validation standards. Chassis chooses to prioritize functional accessibility over validation conformance in this case.
Because the <summary> element has a button role by default (which overrides the roles of its child elements), heading elements inside <summary> are not recognized by assistive technologies like screen readers.
To create accessible accordions with proper heading hierarchy, swap the ARIA roles between the <summary> and heading elements:
- Add
role="heading"andaria-levelattributes to the<summary>element. - Add
role="button"andaria-expandedattributes to the heading element inside.
This ensures screen readers correctly announce both the heading structure and the interactive button functionality.
- The
aria-levelshould match the appropriate heading level in the document hierarchy. - The
aria-expandedattribute will be automatically managed by the accordion JavaScript.
For example:
<details>
<summary role="heading" aria-level="3">
<h3 class="accordion-title" role="button" aria-expanded="false">Accordion Item #1</h3>
</summary>
<div class="accordion-body">
<!-- Content -->
</div>
</details>
This approach preserves the document's heading structure while maintaining the interactive behavior expected from accordion components.
CSS
This component can be customized using CSS variables, allowing for styles to be modified dynamically on the page. These CSS variables are part of Chassis CSS's design token system, giving design teams control over component appearance. See the design tokens page for more details.
Custom properties
These CSS variables control the component's appearance and can be modified dynamically on the page. Components use cascading variables, allowing seamless variations in size, color, and style without redundant style declarations through component inheritance and the context class system.
// Typography variables - Control text appearance for accordion headers and content
@include map-font($accordion-title-font, accordion, title);
@include map-font($accordion-body-font, accordion, body);
// Colors - Define the visual treatment for all accordion states
--#{$prefix}item-fg-color: var(--#{$prefix}accordion-item-fg-color, #{$accordion-item-fg-color});
--#{$prefix}item-bg-color: var(--#{$prefix}accordion-item-bg-color, #{$accordion-item-bg-color});
--#{$prefix}title-fg-color: var(--#{$prefix}accordion-title-fg-color, #{$accordion-title-fg-color});
--#{$prefix}title-bg-color: var(--#{$prefix}accordion-title-bg-color, #{$accordion-title-bg-color});
--#{$prefix}title-fg-active: var(--#{$prefix}accordion-title-fg-active, #{$accordion-title-fg-active});
--#{$prefix}title-bg-active: var(--#{$prefix}accordion-title-bg-active, #{$accordion-title-bg-active});
--#{$prefix}indicator-idle-color: var(--#{$prefix}accordion-indicator-idle-color, #{$accordion-indicator-idle-color});
--#{$prefix}indicator-active-color: var(--#{$prefix}accordion-indicator-active-color, #{$accordion-indicator-active-color});
--#{$prefix}border-color: var(--#{$prefix}accordion-border-color, #{$accordion-border-color});
// Spacing - Control padding and margins for consistent layout
--#{$prefix}title-gap: var(--#{$prefix}accordion-gap, #{$accordion-gap});
--#{$prefix}title-padding-y: var(--#{$prefix}accordion-title-padding-y, #{$accordion-title-padding-y});
--#{$prefix}title-padding-x: var(--#{$prefix}accordion-title-padding-x, #{$accordion-title-padding-x});
--#{$prefix}body-padding-t: var(--#{$prefix}accordion-body-padding-t, #{$accordion-body-padding-t});
--#{$prefix}body-padding-b: var(--#{$prefix}accordion-body-padding-b, #{$accordion-body-padding-b});
--#{$prefix}body-padding-s: var(--#{$prefix}accordion-body-padding-s, #{$accordion-body-padding-s});
--#{$prefix}body-padding-e: var(--#{$prefix}accordion-body-padding-e, #{$accordion-body-padding-e});
// Utilities - Control appearance details and interactive behavior
--#{$prefix}indicator-icon: var(--#{$prefix}accordion-indicator-icon, #{escape-svg($accordion-indicator-icon)});
--#{$prefix}indicator-size: var(--#{$prefix}accordion-indicator-size, #{$accordion-indicator-size});
--#{$prefix}border-width: var(--#{$prefix}accordion-border-width, #{$accordion-border-width});
--#{$prefix}border-radius: var(--#{$prefix}accordion-border-radius, #{$accordion-border-radius});
--#{$prefix}inner-border-radius: var(--#{$prefix}accordion-inner-border-radius, #{$accordion-inner-border-radius});
--#{$prefix}title-focus-box-shadow: var(--#{$prefix}accordion-title-focus-box-shadow, #{$accordion-title-focus-box-shadow});
--#{$prefix}transition: var(--#{$prefix}accordion-transition, #{$accordion-transition});
--#{$prefix}title-transition: var(--#{$prefix}accordion-title-transition, #{$accordion-title-transition});
--#{$prefix}indicator-transform: var(--#{$prefix}accordion-indicator-transform, #{$accordion-indicator-transform});
--#{$prefix}indicator-transition: var(--#{$prefix}accordion-indicator-transition, #{$accordion-indicator-transition});
Sass variables
These Sass variables are also exposed as CSS custom properties using the --cx-
prefix. A Sass variable $variable-name becomes available as --cx-variable-name in CSS, allowing for styles to be modified dynamically on the
page. See the
context components
page for more details.
//$accordion-border-width: var(--#{$prefix}border-width-medium);
//$accordion-border-color: var(--#{$prefix}border-subtle);
//$accordion-border-radius: var(--#{$prefix}border-radius-medium);
// $accordion-indicator: url("data:image/svg+xml,#{$accordion-indicator-icon}");
$accordion-inner-border-radius: #{calc($accordion-border-radius - $accordion-border-width)};
$accordion-transition: $transition-collapse;
$accordion-title-transition: $button-transition, border-radius .15s ease;
$accordion-indicator-transition: transform .2s ease-in-out;
$accordion-indicator-transform: rotate(-180deg);
$accordion-title-focus-box-shadow: $focus-ring-box-shadow; //$button-focus-box-shadow;
// These variables are not exposed as CSS variables.
$accordion-item-fg-color-context: var(--#{$prefix}fg-main);
$accordion-item-bg-color-context: var(--#{$prefix}bg-main);
$accordion-title-fg-color-context: var(--#{$prefix}fg-main);
$accordion-title-bg-color-context: var(--#{$prefix}bg-main);
$accordion-title-fg-active-context: var(--#{$prefix}fg-main);
$accordion-title-bg-active-context: var(--#{$prefix}bg-main);
$accordion-indicator-idle-context: var(--#{$prefix}icon-subtle);
$accordion-indicator-active-context: var(--#{$prefix}icon-main);
$accordion-border-color-context: var(--#{$prefix}border-subtle);
Design tokens
These design tokens with $cx prefixes are managed by design teams in Figma using the Tokens
Studio plugin. See the design tokens page for more details.
// Font
$accordion-title-font: $cx-font-accordion-medium-title;
$accordion-body-font: $cx-font-accordion-medium-body;
$accordion-large-title-font: $cx-font-accordion-large-title;
$accordion-large-body-font: $cx-font-accordion-large-body;
$accordion-small-title-font: $cx-font-accordion-small-title;
$accordion-small-body-font: $cx-font-accordion-small-body;
// Color
$accordion-item-fg-color: $cx-color-accordion-item-fg-color;
$accordion-item-bg-color: $cx-color-accordion-item-bg-color;
$accordion-title-fg-color: $cx-color-accordion-title-fg-idle;
$accordion-title-bg-color: $cx-color-accordion-title-bg-idle;
$accordion-title-fg-active: $cx-color-accordion-title-fg-active;
$accordion-title-bg-active: $cx-color-accordion-title-bg-active;
$accordion-indicator-idle-color: $cx-color-accordion-indicator-idle;
$accordion-indicator-active-color: $cx-color-accordion-indicator-active;
$accordion-border-color: $cx-color-accordion-border-main;
// Size
$accordion-indicator-size: $cx-size-accordion-medium-indicator;
$accordion-large-indicator-size: $cx-size-accordion-large-indicator;
$accordion-small-indicator-size: $cx-size-accordion-small-indicator;
// Spacing
$accordion-title-padding-y: $cx-space-accordion-medium-title-padding-y;
$accordion-title-padding-x: $cx-space-accordion-medium-title-padding-x;
$accordion-body-padding-t: $cx-space-accordion-medium-body-padding-t;
$accordion-body-padding-b: $cx-space-accordion-medium-body-padding-b;
$accordion-body-padding-s: $cx-space-accordion-medium-body-padding-s;
$accordion-body-padding-e: $cx-space-accordion-medium-body-padding-e;
$accordion-gap: $cx-space-accordion-medium-gap;
$accordion-large-title-padding-y: $cx-space-accordion-large-title-padding-y;
$accordion-large-title-padding-x: $cx-space-accordion-large-title-padding-x;
$accordion-large-body-padding-t: $cx-space-accordion-large-body-padding-t;
$accordion-large-body-padding-b: $cx-space-accordion-large-body-padding-b;
$accordion-large-body-padding-s: $cx-space-accordion-large-body-padding-s;
$accordion-large-body-padding-e: $cx-space-accordion-large-body-padding-e;
$accordion-large-gap: $cx-space-accordion-large-gap;
$accordion-small-title-padding-y: $cx-space-accordion-small-title-padding-y;
$accordion-small-title-padding-x: $cx-space-accordion-small-title-padding-x;
$accordion-small-body-padding-t: $cx-space-accordion-small-body-padding-t;
$accordion-small-body-padding-b: $cx-space-accordion-small-body-padding-b;
$accordion-small-body-padding-s: $cx-space-accordion-small-body-padding-s;
$accordion-small-body-padding-e: $cx-space-accordion-small-body-padding-e;
$accordion-small-gap: $cx-space-accordion-small-gap;
// Borders
$accordion-border-width: $cx-border-width-accordion-main;
$accordion-border-radius: $cx-border-radius-accordion-main;
// Icon
$accordion-indicator-icon: svg-icon($cx-icon-accordion-indicator);