Accordion
How the Accordion works with a keyboard and assistive tech, and where it stands against WCAG 2.2 AA.
Each Accordion header is a native <button> inside a heading, so the browser supplies its role, focus and keys. The component adds the disclosure state, ties each header to its panel, and keeps a closed panel out of reach. It follows the WAI-ARIA Accordion pattern and is held to WCAG 2.2 AA.
Keyboard#
Moves to the next header, or into the content of an open panel. A closed panel and a disabled header are skipped.
Moves focus back the same way.
Opens or closes the panel under the focused header.
Opens or closes the panel under the focused header.
Semantics#
<h3><button type="button">The header is a button inside a heading, so it can be found by heading navigation. h3 is the preview's level; set the level to fit the page outline.
Alwaysaria-expandedtrue while the panel is open, false while it is closed. This is the state; the plus, minus and chevron only echo it.
Alwaysaria-controlsPoints at the panel's id.
Alwaysrole="region"Labelled by its header through aria-labelledby. With many panels open at once, drop the role so the landmarks list does not fill up.
PanelinertThe panel stays in the page so its height can animate, but nothing inside it can be focused or read until it opens.
CloseddisabledThe header is removed from the tab order and can't be toggled.
Disabledaria-label="Collapse"The 48px button is named by the title while closed and by collapseLabel while open. Pass a label that names the section, such as Collapse Billing.
2.0, openaria-hidden="true"The toggle glyph and the info icon are decorative.
GlyphsColour contrast#
Every variant and state has to meet WCAG 2.2 Level AA. Measure the colours as they land on screen: a translucent hover or press wash over whatever sits behind it.
Header text · Default, Hover, Open
The title against the card in every state, with the hover wash laid over white. Titles are 16–18px Medium, below the large-text threshold, so 4.5:1 applies.
WCAG 1.4.3 Contrast (Minimum) ↗Panel text and link · Open
Body copy is #2a2a2a or #6d6d6d on white (5.17:1 for the lighter one). The 3.0 read-only card is #f2f2f2, where #6d6d6d measures 4.62:1. The 2.0 link is #005cf8 on white, 5.40:1.
WCAG 1.4.3 Contrast (Minimum) ↗Toggle glyph · Default
The plus or chevron is #8f8f8f on white, 3.23:1. It is decorative, since aria-expanded carries the state and the open panel shows it, but it still clears 3:1. The 3.0 red toggle measures 3.64:1.
WCAG 1.4.11 Non-text Contrast ↗Focus indicator · Focus visible
A 2px #1a6ef8 ring 2px off the whole card, on keyboard focus only: 4.54:1 against white.
WCAG 1.4.11 Non-text Contrast ↗WCAG 2.4.13 Focus Appearance ↗Disabled · Disabled
Inactive headers are exempt. The disabled card is #fcfcfc with a #6d6d6d title and a #cbcbcb toggle.
WCAG 1.4.3 Contrast (Minimum) ↗Measured contrast#
Header text against the card in each state, with hover washes laid over white; the [05] badge is measured against its own pale green fill. 3 of 21 pairs fall below their minimum (4.5:1 for text, 3:1 for graphics) and are marked in amber.
Motion#
- A panel opens and closes with a 220ms height change; under prefers-reduced-motion it snaps open and shut.
- Hover colour changes take 150ms and are also turned off under reduced motion.
Checklist#
Set the heading level to fit the page: an accordion under an h2 uses h3 headers.
Header text says what is in the panel, so people can choose without opening every one.
The [05] badge, #229a14 on #f4fef2, measures under 4.5:1. Use a darker green for its text before the code library ships.
Up, Down, Home and End between headers are optional in the WAI-ARIA pattern and are not provided; Tab reaches every header.
In 2.0, give collapseLabel the section's name. Several buttons all called Collapse can't be told apart in a list of controls.
Don't hide content everyone needs behind a header; a search on the page can't find text in a closed panel.
