Skip to main content

Theme config

Theme mode

Color palette

Grays

Border radii/radiuses/radiopedes/you know
Border radius
Field border radius
Button border radius
All
Components
Guides
API
Recent

Components

Accordion

Let's you show and hide stuff. Uses the native HTML arrow, check out how to add your own custom marker.

Full support Supported since v131. Partial support Missing: container-style-queries, interpolate-size. Partial support Missing: interpolate-size.

Basics

Accordion

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo. Nam tempor euismod nisi ac ornare. Pellentesque id sapien lacinia, venenatis est aliquam, dignissim elit. Suspendisse potenti. Cras ut ante in libero tempus sodales sed quis dolor.

<details class="ui-accordion ui-card">
<summary id="summary-id" aria-controls="content-id">Accordion</summary>
<div
id="content-id"
class="ui-content"
role="region"
aria-labelledby="summary-id"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales,
nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis
neque ante id justo. Nam tempor euismod nisi ac ornare. Pellentesque id
sapien lacinia, venenatis est aliquam, dignissim elit. Suspendisse
potenti. Cras ut ante in libero tempus sodales sed quis dolor.
</p>
</div>
</details>

Variants

Add one of the variant classes (.ui-card, .ui-outlined, .ui-elevated, .ui-tonal) to the <details> element to change how it looks.

Text

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo.

Elevated

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo.

Outlined

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo.

Tonal

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo.

<!-- Text (default) -->
<details class="ui-accordion ui-card">
<summary>Text</summary>
<div class="ui-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales,
nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis
neque ante id justo.
</p>
</div>
</details>
<!-- Elevated -->
<details class="ui-accordion ui-card ui-elevated">
<summary>Elevated</summary>
<div class="ui-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales,
nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis
neque ante id justo.
</p>
</div>
</details>
<!-- Outlined -->
<details class="ui-accordion ui-card ui-outlined">
<summary>Outlined</summary>
<div class="ui-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales,
nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis
neque ante id justo.
</p>
</div>
</details>
<!-- Tonal -->
<details class="ui-accordion ui-card ui-tonal">
<summary>Tonal</summary>
<div class="ui-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales,
nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis
neque ante id justo.
</p>
</div>
</details>

Accordion group

Group multiple accordions by wrapping them in a .ui-card element with role="group". To theme the entire group, apply the variant class to the parent container.

Accordion title

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo.

Accordion title

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo.

Accordion title

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo.

<div class="ui-card ui-outlined" role="group">
<details class="ui-accordion ui-card">
<summary>Accordion title</summary>
<div class="ui-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero,
ac mollis neque ante id justo.
</p>
</div>
</details>
<details class="ui-accordion ui-card">
<summary>Accordion title</summary>
<div class="ui-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero,
ac mollis neque ante id justo.
</p>
</div>
</details>
<details class="ui-accordion ui-card">
<summary>Accordion title</summary>
<div class="ui-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero,
ac mollis neque ante id justo.
</p>
</div>
</details>
</div>

Mutually exclusive

Set the name prop to allow only one accordion in a group to be open at a time.

Accordion title

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo.

Accordion title

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo.

Accordion title

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo.

<div class="ui-card ui-outlined" role="group">
<details class="ui-accordion ui-card" name="example-group">
<summary>Accordion title</summary>
<div class="ui-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero,
ac mollis neque ante id justo.
</p>
</div>
</details>
<details class="ui-accordion ui-card" name="example-group">
<summary>Accordion title</summary>
<div class="ui-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero,
ac mollis neque ante id justo.
</p>
</div>
</details>
<details class="ui-accordion ui-card" name="example-group">
<summary>Accordion title</summary>
<div class="ui-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus
sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero,
ac mollis neque ante id justo.
</p>
</div>
</details>
</div>

Actions

Include interactive elements in the header by using the .ui-actions class.

Accordion with actions

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo. Nam tempor euismod nisi ac ornare.

<details open class="ui-accordion ui-card ui-elevated">
<summary id="summary1" aria-controls="content1">
Accordion with actions
</summary>
<div
id="content1"
class="ui-content"
role="region"
aria-labelledby="summary1"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales,
nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis
neque ante id justo. Nam tempor euismod nisi ac ornare.
</p>
</div>
<div class="ui-actions">
<button class="ui-button">Cancel</button>
<button class="ui-button">Agree</button>
</div>
</details>

Custom marker

Replace the default marker by adding an SVG inside the summary.

Custom marker

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo. Nam tempor euismod nisi ac ornare. Pellentesque id sapien lacinia, venenatis est aliquam, dignissim elit. Suspendisse potenti. Cras ut ante in libero tempus sodales sed quis dolor.

<details class="ui-accordion ui-card ui-outlined">
<summary id="summary1" aria-controls="content1">
Custom marker
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M4.293 8.293a1 1 0 0 1 1.414 0L12 14.586l6.293-6.293a1 1 0 1 1 1.414 1.414l-7 7a1 1 0 0 1-1.414 0l-7-7a1 1 0 0 1 0-1.414"
/>
</svg>
</summary>
<div
id="content1"
class="ui-content"
role="region"
aria-labelledby="summary1"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales,
nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis
neque ante id justo. Nam tempor euismod nisi ac ornare. Pellentesque id
sapien lacinia, venenatis est aliquam, dignissim elit. Suspendisse
potenti. Cras ut ante in libero tempus sodales sed quis dolor.
</p>
</div>
</details>

Accessibility

The WAI-ARIA guidelines for accordions recommend:

  • summary element
    • adding id and aria-controls
    • adding aria-expanded (if using JS)
  • content wrapper
    • adding id, role and aria-labelledby

Anatomy

  1. <details class="ui-accordion">: a wrapper for the accordion
  2. <summary>: a wrapper for the accordion header
  3. & > .ui-content (optional): a wrapper for the accordion content
  4. & > .ui-actions (optional): a wrapper that groups a set of buttons
Accordion title

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales, nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis neque ante id justo. Nam tempor euismod nisi ac ornare. Pellentesque id sapien lacinia, venenatis est aliquam, dignissim elit. Suspendisse potenti. Cras ut ante in libero tempus sodales sed quis dolor.

<details class="ui-accordion ui-card anatomy" open>
<!-- Summary -->
<summary id="summary-1" aria-controls="content-1">Accordion title</summary>
<!-- Content -->
<div
id="content-1"
class="ui-content"
role="region"
aria-labelledby="summary-1"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus sodales,
nulla sit amet porttitor rhoncus, lacus ex vestibulum libero, ac mollis
neque ante id justo. Nam tempor euismod nisi ac ornare. Pellentesque id
sapien lacinia, venenatis est aliquam, dignissim elit. Suspendisse
potenti. Cras ut ante in libero tempus sodales sed quis dolor.
</p>
</div>
<!-- Actions -->
<div class="ui-actions">
<button class="ui-button">Cancel</button>
<button class="ui-button">Agree</button>
</div>
</details>

API

Type Modifiers Default Description
Accordion details.ui-accordion - The root element for the accordion. Requires the .ui-accordion class and optionally the .ui-card class for styling.
Group .ui-card[role="group"] - Optional wrapper for accordion groups. To theme the entire group, apply the variant class to this element.
Attribute name - The name of the accordion (used for grouping multiple accordions).
Part & > summary, & > .ui-content, & > .ui-actions - Optional wrappers for child content.
Variants .ui-text, .ui-elevated, .ui-tonal, .ui-outlined .ui-text The variant to use.

Browser support

Full support Supported since v131. Partial support Missing: container-style-queries, interpolate-size. Partial support Missing: interpolate-size.

See also the full browser support guide.

Installation

Dependencies

@layer components.extended {
:where(details.ui-accordion) {
--_actions-gap: var(--size-1);
--_actions-margin-block-start: var(--size-3);
--_actions-padding-block-end: var(--size-1);
--_actions-padding-inline: var(--size-3) var(--size-1);
--_bg-color: transparent;
--_border-color: transparent;
--_border-radius: var(--border-radius, 4px);
--_border-width: 0;
--_content-padding-block: var(--size-2) var(--size-3);
--_content-padding-inline: var(--_padding-inline);
--_margin-inline: var(--size-1);
--_padding-inline: initial;
--_shadow: none;
--_summary-padding-block: var(--size-3);
--_summary-padding-inline: var(--_padding-inline);
--_svg-transition: 0.2s var(--ease-1);
--_transition: 0.2s;
background-color: var(--_bg-color);
border: var(--_border-width) solid var(--_border-color);
border-radius: var(--_border-radius);
box-shadow: var(--_shadow);
display: block;
margin-inline: var(--_margin-inline);
transition: all var(--_transition) ease-out;
&.ui-elevated {
--_bg-color: var(--surface-elevated);
--_margin-inline: 0;
--_padding-inline: var(--size-3);
--_shadow: var(--shadow-3);
}
&.ui-outlined {
--_bg-color: var(--surface-default);
--_border-color: var(--border-color);
--_border-width: 1px;
--_margin-inline: 0;
--_padding-inline: var(--size-3);
}
&.ui-tonal {
--_bg-color: var(--surface-tonal);
--_margin-inline: 0;
--_padding-inline: var(--size-3);
}
/* Accordion animation */
/* https://nerdy.dev/open-and-close-transitions-for-the-details-element */
@media (prefers-reduced-motion: no-preference) {
interpolate-size: allow-keywords;
}
&::details-content {
block-size: 0;
opacity: 0;
overflow-y: clip;
transition:
content-visibility var(--_transition) allow-discrete,
opacity var(--_transition),
block-size var(--_transition);
}
&[open]::details-content {
block-size: auto;
opacity: 1;
}
/* Layout */
& > summary {
background-color: inherit;
cursor: pointer;
font-weight: 700;
padding-block: var(--_summary-padding-block);
padding-inline: var(--_summary-padding-inline);
user-select: none;
&:has(svg) {
align-items: center;
display: flex;
justify-content: space-between;
list-style: none;
&::marker,
&::-webkit-details-marker {
display: none;
}
}
svg {
transition: rotate var(--_svg-transition);
}
}
&[open] > summary svg {
rotate: 180deg;
}
& > .ui-content {
margin-block-start: 0;
padding-block: var(--_content-padding-block);
padding-inline: var(--_content-padding-inline);
}
& > .ui-actions {
display: flex;
gap: var(--_actions-gap);
justify-content: end;
margin-block-start: var(--_actions-margin-block-start);
padding-block-end: var(--_actions-padding-block-end);
padding-inline: var(--_actions-padding-inline);
}
}
/* Accordion group */
:where(.ui-card[role="group"]:has(details.ui-accordion)) {
--_group-radius: var(--border-radius);
--_gutter-color: var(--border-color);
--_item-padding-inline: var(--size-3);
--_item-summary-padding-inline: var(--_item-padding-inline);
display: block;
&.ui-card {
&:not(.ui-tonal, .ui-outlined, .ui-elevated) {
--_item-summary-padding-inline: 0;
}
}
& > .ui-content {
margin-block: 0;
padding: 0;
}
& > details.ui-accordion {
--_border-color: transparent;
--_border-width: 0;
--_margin-inline: 0;
--_padding-inline: var(--_item-padding-inline);
--_shadow: none;
--_summary-padding-inline: var(--_item-summary-padding-inline);
/* Border between accordion items */
& + & {
border-block-start: 1px solid var(--_gutter-color);
border-radius: 0;
}
/* First item */
&:first-of-type {
border-start-end-radius: var(--_group-radius);
border-start-start-radius: var(--_group-radius);
summary {
border-start-end-radius: var(--_group-radius);
border-start-start-radius: var(--_group-radius);
}
}
/* Last item */
&:last-of-type {
border-end-end-radius: var(--_group-radius);
border-end-start-radius: var(--_group-radius);
summary {
border-end-end-radius: var(--_group-radius);
border-end-start-radius: var(--_group-radius);
}
}
}
}
}
@layer components.root {
:where(.ui-card) {
--_bg-tonal: var(--surface-tonal);
--_bg-elevated: var(--surface-elevated);
--_bg-surface: var(--surface-default);
--_border-color: var(--border-color);
--_card-bg-color: var(--_bg-surface);
--_card-border-color: transparent;
--_card-border-width: 0;
--_card-shadow: none;
--_shadow-light: var(--shadow-3);
--_shadow-dark: var(--shadow-4);
--_shadow-elevated: var(--_shadow-light);
@container style(--color-scheme: dark) {
--_shadow-elevated: var(--_shadow-dark);
}
background-color: var(--_card-bg-color);
border-color: var(--_card-border-color);
border-radius: var(--border-radius);
border-style: solid;
border-width: var(--_card-border-width);
box-shadow: var(--_card-shadow);
display: flex;
flex-direction: column;
gap: var(--size-3);
overflow: hidden;
padding-inline: 0;
position: relative;
/* Variants */
&.ui-text {
--_card-bg-color: transparent;
--_card-border-color: transparent;
--_card-border-width: 0;
--_card-shadow: none;
}
&.ui-tonal {
--_card-bg-color: var(--_bg-tonal);
--_card-border-width: 1px;
}
&.ui-elevated {
--_card-bg-color: var(--_bg-elevated);
--_card-shadow: var(--_shadow-elevated);
}
&.ui-outlined {
--_card-bg-color: var(--_bg-surface);
--_card-border-color: var(--_border-color);
--_card-border-width: 1px;
}
& > :where(hgroup, .ui-content) {
padding-inline: var(--size-3);
&:last-child {
padding-block-end: var(--size-3);
}
}
/* Header */
& > hgroup {
padding-block: var(--size-3) 0;
/* Top paragraph */
& > p:first-of-type:first-child {
line-height: 1.3;
}
:where(h1, h2, h3, h4, h5, h6):last-child {
margin-block-end: 0;
}
/* Bottom paragraph */
& > p:last-of-type:last-child:not(:first-child) {
font-size: var(--font-size-1);
}
}
/* Content */
& > .ui-content:where(:only-child, :first-child) {
padding-block: var(--size-3) var(--size-4);
}
/* Actions */
& > .ui-actions {
display: flex;
gap: var(--size-2);
margin-block: var(--size-2) 0;
padding-block-end: var(--size-2);
padding-inline: var(--size-3);
&:has(.ui-button:first-child[class="ui-button"]) {
padding-inline: var(--size-1) var(--size-3);
}
&:has(.ui-button:not([class="ui-button"])) {
padding-block-end: var(--size-2);
}
/* Alignment */
&.ui-align-end {
justify-content: end;
&:has(.ui-button:first-child[class="ui-button"]) {
padding-inline: var(--size-3) var(--size-1);
}
}
}
}
}