Accordion
layoutUSWDS-derivedinteractive
An expandable/collapsible content section, borderless or bordered.
Reference: USWDS documentation ↗
Variants
Bordered Accordion
First section content.
Second section content.
Third section content.
<flex-accordion data-variant="bordered">
<div>
<h3 class="flex-accordion__heading">
<button type="button" class="flex-accordion__button" aria-expanded="false" aria-controls="accordion-panel-b-first">First section</button>
</h3>
<div class="flex-accordion__content" id="accordion-panel-b-first" hidden="">
<p>First section content.</p>
</div>
</div>
<div>
<h3 class="flex-accordion__heading">
<button type="button" class="flex-accordion__button" aria-expanded="true" aria-controls="accordion-panel-b-second">Second section</button>
</h3>
<div class="flex-accordion__content" id="accordion-panel-b-second">
<p>Second section content.</p>
</div>
</div>
<div>
<h3 class="flex-accordion__heading">
<button type="button" class="flex-accordion__button" aria-expanded="false" aria-controls="accordion-panel-b-third">Third section</button>
</h3>
<div class="flex-accordion__content" id="accordion-panel-b-third" hidden="">
<p>Third section content.</p>
</div>
</div>
</flex-accordion>Default Accordion
Congress shall make no law...
A well regulated Militia...
No Soldier shall, in time of peace...
<flex-accordion>
<div>
<h3 class="flex-accordion__heading">
<button type="button" class="flex-accordion__button" aria-expanded="false" aria-controls="accordion-panel-first">First Amendment</button>
</h3>
<div class="flex-accordion__content" id="accordion-panel-first" hidden="">
<p>Congress shall make no law...</p>
</div>
</div>
<div>
<h3 class="flex-accordion__heading">
<button type="button" class="flex-accordion__button" aria-expanded="false" aria-controls="accordion-panel-second">Second Amendment</button>
</h3>
<div class="flex-accordion__content" id="accordion-panel-second" hidden="">
<p>A well regulated Militia...</p>
</div>
</div>
<div>
<h3 class="flex-accordion__heading">
<button type="button" class="flex-accordion__button" aria-expanded="true" aria-controls="accordion-panel-third">Third Amendment</button>
</h3>
<div class="flex-accordion__content" id="accordion-panel-third">
<p>No Soldier shall, in time of peace...</p>
</div>
</div>
</flex-accordion>Multiselectable Accordion
First section content.
Second section content.
Third section content.
<flex-accordion data-multiselectable="true">
<div>
<h3 class="flex-accordion__heading">
<button type="button" class="flex-accordion__button" aria-expanded="true" aria-controls="accordion-panel-m-first">First section</button>
</h3>
<div class="flex-accordion__content" id="accordion-panel-m-first">
<p>First section content.</p>
</div>
</div>
<div>
<h3 class="flex-accordion__heading">
<button type="button" class="flex-accordion__button" aria-expanded="true" aria-controls="accordion-panel-m-second">Second section</button>
</h3>
<div class="flex-accordion__content" id="accordion-panel-m-second">
<p>Second section content.</p>
</div>
</div>
<div>
<h3 class="flex-accordion__heading">
<button type="button" class="flex-accordion__button" aria-expanded="false" aria-controls="accordion-panel-m-third">Third section</button>
</h3>
<div class="flex-accordion__content" id="accordion-panel-m-third" hidden="">
<p>Third section content.</p>
</div>
</div>
</flex-accordion>Contract
Class mapping
| USWDS | Flex | Notes |
|---|---|---|
usa-accordion | <flex-accordion> (custom element) | Container element |
usa-accordion__heading | .flex-accordion__heading | Section heading wrapper |
usa-accordion__button | .flex-accordion__button | Toggle button |
usa-accordion__content | .flex-accordion__content | Collapsible panel |
data-allow-multiple | data-multiselectable | Allow multiple panels open simultaneously |
Verified properties
background-colorfont-sizefont-weightfont-familyline-heightcursorIntentional differences
display: ours = flex, USWDS = inline-block
We use flex for space-between layout with +/- indicator; USWDS uses inline-block with background image
Behavior promises
- ✓ Click button expands content
- ✓ Click again collapses content
- ✓ Default mode: opening one closes others
- ✓ Multiselectable: multiple can be open
- ✓ Keyboard Enter toggles accordion
- ✓ Hover state background matches USWDS
- ✓ Accessibility audit passes with mixed states
Source CSS
flex-accordion {
display: block;
min-inline-size: 0;
overflow: hidden;
/* Bordered variant */
&[data-variant="bordered"] .flex-accordion__button {
border-inline: 1px solid var(--flex-color-border);
}
&[data-variant="bordered"] .flex-accordion__content {
border-inline: 1px solid var(--flex-color-border);
}
}
.flex-accordion__heading {
margin: 0;
}
.flex-accordion__button {
display: flex;
align-items: center;
justify-content: space-between;
inline-size: 100%;
padding: var(--flex-space-md);
background-color: var(--flex-color-bg-subtle);
border: none;
border-block-end: 1px solid var(--flex-color-border);
font-size: var(--flex-text-uswds);
font-weight: 700;
color: var(--flex-color-text);
cursor: pointer;
text-align: start;
&:hover {
background-color: var(
--flex-color-border
); /* @uswds base-lighter (#dfe1e2) */
}
&:focus-visible {
outline: var(--flex-focus-ring);
outline-offset: -4px;
z-index: 1;
position: relative;
}
&::after {
content: "";
inline-size: 1.5rem;
block-size: 1.5rem;
flex-shrink: 0;
margin-inline-start: var(--flex-space-md);
background-color: var(--flex-color-text);
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z'/%3E%3C/svg%3E");
mask-size: contain;
mask-repeat: no-repeat;
}
&[aria-expanded="true"]::after {
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19 13H5v-2h14v2z'/%3E%3C/svg%3E");
}
}
.flex-accordion__content {
padding: var(--flex-space-md);
border-block-end: 1px solid var(--flex-color-border);
font-size: var(--flex-text-uswds);
color: var(--flex-color-text);
line-height: 1.5;
&[hidden] {
display: none;
}
}
A digital services project by Flexion