Skip to content
Development4 min read

A Pure-CSS Accordion (No JavaScript Required)

The humble details element gives you an accessible accordion with zero JavaScript and almost no CSS. Here's how to build one and style it well.

Otter
A Pure-CSS Accordion (No JavaScript Required)

Accordions show up everywhere - FAQ sections, product details, settings panels. The reflex is to reach for a component library or write a bit of JavaScript to toggle each panel open. You almost never need to. HTML has a built-in element for exactly this, and it’s been quietly supported in every browser for years.

Here’s one built from nothing but <details> and a little CSS. Click a row:

Do you work with clients outside Montenegro?
Yes. Most of our work happens over email and calls, so where you are rarely matters.
How long does a typical project take?
Most sites land in three to six weeks, depending on scope and how quickly feedback comes back.
Do I own the site when it's done?
Completely. The code, the domain, the accounts - all yours to keep.

It opens, it closes, it remembers which panels are open. None of that cost a line of script.

The markup

The whole thing is two elements. <details> is the panel, <summary> is the part that’s always visible and does the toggling:

<details>
  <summary>Do you work with clients outside Montenegro?</summary>
  <div>Yes. Most of our work happens over email and calls.</div>
</details>

Click the summary and the browser shows or hides everything after it. Add an open attribute and it starts expanded. Stack a few of these and you have an accordion.

Why this is worth doing

You’re not just saving yourself some JavaScript. The browser gives you a pile of behavior for free:

  • It’s keyboard-operable out of the box - tab to a summary, hit Enter or Space, it toggles.
  • Screen readers announce it correctly as an expandable group, with no aria-expanded for you to wire up and keep in sync.
  • Browser find-in-page can open a closed panel to reveal a match inside it.

Recreating all of that by hand with <div>s and click handlers is exactly the kind of work people quietly get wrong.

Styling the marker

The one rough edge is the default triangle, which looks different in every browser. Hide it and add your own:

summary {
  list-style: none; /* removes the marker in Firefox */
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

summary::-webkit-details-marker {
  display: none; /* removes it in Safari and Chrome */
}

summary::after {
  content: "+";
  transition: transform 0.2s ease;
}

details[open] summary::after {
  transform: rotate(45deg); /* the + turns into an x when open */
}

The trick in that last rule is the details[open] selector. The browser adds and removes the open attribute as the panel toggles, so you can style the open state purely in CSS. Here we rotate a + by 45 degrees so it reads as a close icon - one character, no icon font, no swap.

Animating the open and close

This is the part people reach for JavaScript to fix, because <details> snaps open instantly by default and animating to height: auto was impossible in CSS for years. It isn’t anymore. Two newer features handle it:

:root {
  interpolate-size: allow-keywords; /* lets height: auto animate */
}

::details-content {
  height: 0;
  overflow: hidden;
  transition: height 0.3s ease;
}

details[open]::details-content {
  height: auto;
}

::details-content targets everything inside the panel except the summary, and interpolate-size is what finally lets a transition run to auto. Treat this as a progressive enhancement: browsers that don’t support it yet just open instantly, which was the old behavior anyway and is perfectly fine.

When to reach for it

Any time the pattern is “click a label, reveal some content” - FAQs, spec tables, filter groups, disclosure widgets - start here and only add JavaScript if you hit something the element genuinely can’t do, like having one panel close another automatically. For a plain FAQ section it’s hard to justify anything more. Leaning on what the browser already gives you is a big part of how you keep a site fast and accessible.

Back to all articles
Share

Keep Reading

Say hello

Let's make something
you're proud of.

Tell us what you're working on - even a rough idea is plenty. Book a quick call, or send a message and we'll reply like actual humans, usually within a day.

Book a call

A short intro call - no pitch, just a chat about what you're working on.

Prefer email?

[email protected]

Based in

Montenegro

Working with people here, and anywhere the wifi reaches.

Prefer to write?