← Back to UI screens

Live: try it with the mouse and the keyboard (Tab, arrows, Escape).

ScreenshotAccordion component — web, retro style
Theme

Accordion component — web, retro style

Accordion UI component for websites and web apps, shown in Steadyfit, a fictional health product. Shows an accordion with one section open, a disabled section, chevrons that rotate, and every header state (default, hover, focus-visible, open, disabled). Retro style: warm cream, soft Fraunces headings with DM Sans, outlined cards and offset colour shadows. Comes with copyable HTML, CSS and a few lines of plain JavaScript (keyboard support and ARIA per the WAI-ARIA Authoring Practices), a live demo, and a DESIGN.md with light and dark colour tokens.

Open live HTML ↗ Download DESIGN.md
Pattern
Accordion
Device
Web
Style
Retro
Product (fictional)
Steadyfit
Category
Health

Spec

Colours (light)
background #fffaf5 · surface #f8ebdc · text #2a1e10 · muted #6f614f · primary #c74b52 · accent #42953d
Colours (dark)
background #1a1207 · surface #2b2113 · text #f7f1e9 · muted #bdaf9e · primary #ff9c9c · accent #80d479
Fonts
Fraunces (headings), DM Sans (body), JetBrains Mono (code) · Google Fonts, under their own licences
Light and dark
Both included; follows the system setting
ARIA pattern
Accordion (WAI-ARIA Authoring Practices)
Keyboard
Enter or Space toggles; arrows, Home and End move
States
default, hover, focus-visible, open, disabled
accordionwebhealthlist

Code

Paste the HTML where the component goes, the CSS into your stylesheet and the script before </body>. The tokens block holds the light and dark colours; swap in your own.

HTML
<div class="mgd-acc">
  <div class="mgd-acc__item">
    <h3 class="mgd-acc__h"><button class="mgd-acc__btn" type="button" id="acc-included-btn" aria-expanded="true" aria-controls="acc-included">What's included in the plan?<span class="mgd-acc__icon"><svg class="i" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 9l7 7 7-7"/></svg></span></button></h3>
    <div class="mgd-acc__panel" id="acc-included" role="region" aria-labelledby="acc-included-btn"><p>Unlimited workouts, habit tracking, weekly check-ins with your coach and offline access on two devices.</p></div>
  </div>
  <div class="mgd-acc__item">
    <h3 class="mgd-acc__h"><button class="mgd-acc__btn" type="button" id="acc-billing-btn" aria-expanded="false" aria-controls="acc-billing">How does billing work?<span class="mgd-acc__icon"><svg class="i" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 9l7 7 7-7"/></svg></span></button></h3>
    <div class="mgd-acc__panel" id="acc-billing" role="region" aria-labelledby="acc-billing-btn" hidden><p>You pay monthly or yearly. Yearly plans are billed once and renew on the same date; we email you a week before.</p></div>
  </div>
  <div class="mgd-acc__item">
    <h3 class="mgd-acc__h"><button class="mgd-acc__btn" type="button" id="acc-pause-btn" aria-expanded="false" aria-controls="acc-pause">Can I pause my plan?<span class="mgd-acc__icon"><svg class="i" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 9l7 7 7-7"/></svg></span></button></h3>
    <div class="mgd-acc__panel" id="acc-pause" role="region" aria-labelledby="acc-pause-btn" hidden><p>Yes, for up to 8 weeks a year. Your streaks and history stay as they are while you are paused.</p></div>
  </div>
  <div class="mgd-acc__item">
    <h3 class="mgd-acc__h"><button class="mgd-acc__btn" type="button" id="acc-family-btn" aria-expanded="false" aria-controls="acc-family" aria-disabled="true">Family sharing (coming soon)<span class="mgd-acc__icon"><svg class="i" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 9l7 7 7-7"/></svg></span></button></h3>
    <div class="mgd-acc__panel" id="acc-family" role="region" aria-labelledby="acc-family-btn" hidden><p>Family plans arrive in the spring.</p></div>
  </div>
</div>
CSS
/* Tokens (light + dark) */
:root{--bg:#fffaf5;--surface:#f8ebdc;--border:#d8cab9;--text:#2a1e10;--muted:#6f614f;--primary:#c74b52;--on-primary:#ffffff;--accent:#42953d;--font-h:"Fraunces",Georgia,serif;--font-b:"DM Sans",system-ui,sans-serif;--hw:700;
--c-bw:2px;--c-line:var(--text);--c-r:10px;--c-pill:10px;--c-sh:3px 3px 0 var(--primary);--c-pop:5px 5px 0 var(--text);--c-tt:none;--c-ls:0;--c-fw:700;--c-fs:14px;--c-ring:3px solid var(--accent);--c-ind:3px;color-scheme:light}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--bg:#1a1207;--surface:#2b2113;--border:#433729;--text:#f7f1e9;--muted:#bdaf9e;--primary:#ff9c9c;--on-primary:#111111;--accent:#80d479;color-scheme:dark}
}
:root[data-theme="dark"]{--bg:#1a1207;--surface:#2b2113;--border:#433729;--text:#f7f1e9;--muted:#bdaf9e;--primary:#ff9c9c;--on-primary:#111111;--accent:#80d479;color-scheme:dark}

/* Component */
.mgd-sr{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.mgd-acc{max-width:720px;border-top:var(--c-bw) solid var(--text)}
.mgd-acc__item{border-bottom:var(--c-bw) solid var(--text)}
.mgd-acc__h{margin:0;font:inherit}
.mgd-acc__btn{width:100%;display:flex;align-items:center;justify-content:space-between;gap:16px;min-height:56px;padding:14px 4px;border:0;background:none;color:var(--text);font:600 16px/1.35 var(--font-b);text-transform:var(--c-tt);letter-spacing:var(--c-ls);text-align:left;cursor:pointer;border-radius:var(--c-r);transition:background-color .12s}
.mgd-acc__btn:hover,.mgd-acc__btn.is-hover{background:color-mix(in oklab,var(--primary) 7%,transparent)}
.mgd-acc__btn:focus-visible,.mgd-acc__btn.is-focus{outline:var(--c-ring);outline-offset:-2px}
.mgd-acc__btn[aria-disabled="true"],.mgd-acc__btn.is-off{opacity:.45;cursor:not-allowed;background:none}
.mgd-acc__icon{flex:none;width:28px;height:28px;display:grid;place-items:center;border-radius:var(--c-r);background:color-mix(in oklab,var(--primary) 12%,transparent);color:var(--text);transition:transform .16s}
.mgd-acc__btn[aria-expanded="true"] .mgd-acc__icon,.mgd-acc__btn.is-on .mgd-acc__icon{transform:rotate(180deg)}
.mgd-acc__panel{padding:0 4px 18px;color:var(--muted);max-width:62ch}
.mgd-acc__panel p{margin:0}
@media (prefers-reduced-motion:reduce){.mgd-acc,.mgd-acc *{transition:none!important;animation-duration:2.4s!important}}
JavaScript
document.querySelectorAll(".mgd-acc").forEach(function (acc) {
  var btns = [].slice.call(acc.querySelectorAll(".mgd-acc__btn"));
  acc.addEventListener("click", function (e) {
    var b = e.target.closest(".mgd-acc__btn"); if (!b || b.getAttribute("aria-disabled") === "true") return;
    var open = b.getAttribute("aria-expanded") !== "true";
    b.setAttribute("aria-expanded", open); document.getElementById(b.getAttribute("aria-controls")).hidden = !open;
  });
  acc.addEventListener("keydown", function (e) {
    var i = btns.indexOf(document.activeElement); if (i < 0) return;
    var n = e.key === "ArrowDown" ? btns[(i + 1) % btns.length] : e.key === "ArrowUp" ? btns[(i - 1 + btns.length) % btns.length] : e.key === "Home" ? btns[0] : e.key === "End" ? btns[btns.length - 1] : null;
    if (n) { e.preventDefault(); n.focus(); }
  });
});

DESIGN.md

Component section (states, ARIA, keyboard)
## Component: Accordion

Stacked sections that expand in place; each header is a real button inside a heading.

- **Pattern:** WAI-ARIA Authoring Practices, Accordion (https://www.w3.org/WAI/ARIA/apg/patterns/accordion/)
- **Roles and attributes:** Each header is a <button> inside an <h3> with aria-expanded and aria-controls; each panel has role="region" and aria-labelledby, and is hidden with the hidden attribute when closed.
- **States drawn:** default, hover, focus-visible, open, disabled
- **Focus:** a visible `:focus-visible` outline (3px solid accent), never removed
- **Style knobs (retro):** border 2px, corners 10px, shadow `3px 3px 0 var(--primary)`, labels sentence case
- **Motion:** transitions are short (≤160ms) and switched off under `prefers-reduced-motion: reduce`
- **Code:** HTML + CSS + a few lines of plain JavaScript (no libraries); colours come only from the tokens above, so light and dark both work

### Keyboard
- **Enter / Space:** expand or collapse the focused section
- **Up / Down arrow:** previous / next header
- **Home / End:** first / last header

### Licence
Original Made Good Designs code: free to use and adapt in any project, including commercial ones, with no credit needed. Fonts are Google Fonts under their own licences.
AI

Build this with your AI

Fonts: Fraunces + DM Sans (Google Fonts)

Writing about this component?

More accordion components

Accordion component — web, minimal (Steadyfit)
web · minimal
Accordion component — web, editorial (Steadyfit)
web · editorial
Accordion component — web, brutalist (Steadyfit)
web · brutalist
Accordion component — web, luxury (Steadyfit)
web · luxury
Accordion component — web, playful (Steadyfit)
web · playful
Accordion component — web, corporate (Steadyfit)
web · corporate
Accordion component — web, monochrome (Steadyfit)
web · monochrome
Accordion component — mobile, retro (Steadyfit)
mobile · retro
Building with an AI coding agent? Every screen here is also in the free Made Good Designs MCP server: ask Claude, Cursor or ChatGPT to search_ui_screens (e.g. “billing settings, editorial style”), get_ui_flow for a whole journey, and get_ui_screen_code to pull the HTML and DESIGN.md straight into your project.

Save to board