Skip to content
Animation

Animated accordions without JavaScript using details

How details and summary carry an accordion without script, how name keeps only one entry open, how ::details-content and interpolate-size animate the height to auto and what Firefox and Safari show of it so far.

9 min readBy Amelie RoesmannUpdated: 09 November 2026
AnimationHTMLCSSAccordion

In most projects an accordion is a small state machine: a button with aria-expanded, state for the open entry and a library that measures the height so the content opens smoothly. The details element does most of that by itself, in every major browser since 2020. Three newer pieces close the rest. The name attribute keeps only one entry in a group open, Baseline since September 2024. The ::details-content pseudo-element makes the content area styleable, Baseline since September 2025. And interpolate-size allows transitions to height: auto, so far only in Chrome and Edge from version 129. This guide builds an accordion without script from them, shows the Tailwind version and says what Firefox and Safari see of it today.

The short version
  • details and summary bring focus, Enter and Space, the open or closed state and search inside closed content with them. A custom button with aria-expanded has to rebuild all of that.
  • Several details with the same name form a group in which at most one entry is open. Chrome and Edge have supported that since version 120, Firefox since 130, Safari since 17.2.
  • ::details-content targets the content area of details, interpolate-size: allow-keywords on :root makes height: auto animatable. For closing, content-visibility with allow-discrete belongs in the transition.
  • According to MDN data from November 2026, interpolate-size only runs in Chrome and Edge. Firefox and Safari open the same accordion without a transition but correctly, so no script fallback is needed.
01

Why is details enough for an accordion?

Because details already brings the behaviour a custom accordion laboriously rebuilds. summary is keyboard reachable, Enter and Space toggle it, and the open or closed state reaches screen readers without a script setting aria-expanded. The element has run in every major browser since January 2020.

One advantage only shows when it is missing. The browser's find in page locates text in closed entries too and opens the matching one. According to MDN, Chrome has done that since version 97, Firefox since 148 and Safari since 26.2, there still with a bug when scrolling to the match. An accordion made of a div and a button, by contrast, hides its content in a way that search does not find or does not expand.

What details could not do for a long time was styling. The content appeared all at once, and to open it smoothly you had to wrap it in an element of its own and measure the height with a script. That is exactly what the three pieces in the next sections change.

<details>  <summary>How long does delivery take?</summary>  <p>Two to four working days within the country.</p></details>
One entry, without script. summary is the question, the rest is the answer.
Only text in summaryA link or button inside summary triggers two things on click: its own action and toggling the entry. For screen readers it also sits inside an element that already behaves like a button. Links belong in the answer, not in the question.
02

How does an accordion keep only one entry open?

With the same value in the name attribute on every details in the group. When someone opens an entry, the browser closes the one that was open. Chrome and Edge have supported that since version 120, Firefox since 130 and Safari since 17.2. Since September 2024 the attribute has therefore counted as Baseline.

name does not prevent all entries from being closed. A click on the open one closes it as usual. And if two entries carry open in the markup, only one stays open: in a test with Chrome 153 it was the first. If you want to open an entry in advance, set open in exactly one place.

Whether a group should be exclusive at all is a separate question. In an FAQ where someone wants to compare two answers, it gets in the way when the first one collapses. For settings or steps that follow one another, it helps, because the page stays short.

<details name="faq" open>  <summary>Can I change my plan later?</summary>  <p>Yes, at the end of each billing period.</p></details><details name="faq">  <summary>Is there a free trial?</summary>  <p>Fourteen days, no card required.</p></details><details name="faq">  <summary>Where is my data stored?</summary>  <p>In data centres within the EU.</p></details>
Three entries, one group. The first is open on load.
03

What is ::details-content?

A pseudo-element for everything in details except summary. It can be styled like a box, with height, overflow, spacing and transitions, without wrapping the content in an extra element. Chrome and Edge have supported it since version 131, Firefox since 143 and Safari since 18.4. Since September 2025 it has counted as Baseline.

That became possible because Chrome changed how the content area is rendered in version 131: it is now a block instead of an element that only passes its children through. Only with that does it have a height of its own that can be set and animated.

Safari has one limitation. Pseudo-elements cannot be chained onto ::details-content there, so a ::details-content::before does not apply. If you need a divider or a gradient on the content, put it on an element inside the answer.

details::details-content {  padding-inline: 1rem;  border-inline-start: 2px solid currentColor;}
The content area as a box of its own, without an extra div.
04

How do you animate the height of a details element to auto?

With interpolate-size: allow-keywords on :root and a transition on height on ::details-content. Until now auto was not a value a browser could calculate between it and a number, so the height jumped. interpolate-size allows exactly that calculation. The property is inherited, so one line on :root covers the whole page.

That is enough for opening. Closing needs a second entry in the transition. A closed details hides its content through content-visibility, and that happens immediately, before the height could shrink. With content-visibility and allow-discrete in the transition, the switch waits until the end of the duration and the content stays visible while it collapses. allow-discrete has run since Chrome 117, Firefox 129 and Safari 17.4.

overflow: clip cuts the content off during the motion. hidden would work too, but clip does not create a scroll container. In a test with Chrome 153 the accordion opened and closed smoothly in both directions this way, even when name collapsed the entry that was open before.

:root {  interpolate-size: allow-keywords;} details::details-content {  height: 0;  overflow: clip;  transition:    height 300ms ease,    content-visibility 300ms ease allow-discrete;} details[open]::details-content {  height: auto;} @media (prefers-reduced-motion: reduce) {  details::details-content {    transition: none;  }}
Opening and closing with motion. Reduced motion switches it off.
max-height as a workaround
  • The height runs to a guessed value such as 500 pixels instead of the content.
  • With short answers, closing feels delayed because the empty part shrinks first.
  • If an answer is longer than the value, it gets cut off.
height: auto with interpolate-size
  • The height runs exactly to the content, however long the answer is.
  • Duration and curve feel the same when opening and closing.
  • No value in the stylesheet that goes stale with the next longer text.
05

What do Firefox and Safari show of the animation?

An accordion that opens and closes correctly, but without motion. In November 2026, MDN's browser data lists interpolate-size only for Chrome and Edge from version 129, as experimental. caniuse shows no support in Firefox up to version 162 and Safari up to 27.3 and arrives at around 74 percent of global usage in October 2026.

Because both browsers know ::details-content, height: 0 and height: auto still apply there. Only the transition between them is missing, because without interpolate-size auto is not a target that can be calculated towards. The result is the familiar details, and no fallback is needed to repair anything.

The calc-size function, which could animate auto without the property on :root, does not help here. It is available in the same browsers as interpolate-size, so again only in Chrome and Edge from 129.

Motion as a bonus, not a requirementThe question is not whether every browser shows the animation, but whether a browser without it loses anything. With an accordion it loses nothing: the answer is there as soon as someone clicks. A library that measures the height only pays off when the motion itself explains something, for instance when an entry is part of a larger animation.
06

How do you build the accordion with Tailwind CSS?

With the details-content variant for the content area, open for the open state and an arbitrary property for interpolate-size. Checked in Tailwind CSS 4.3.5: details-content: writes to ::details-content, open: matches details with the open attribute, and transition-discrete sets transition-behavior: allow-discrete. There is no dedicated class for interpolate-size, the square bracket syntax generates it.

The variants can be chained. open:details-content:h-auto gives the content of an open details height auto, and because this rule is more specific than details-content:h-0, it wins without detours. motion-reduce:details-content:transition-none switches the motion off when reduced motion is set.

In React the accordion stays free of state. name and open are ordinary attributes, and the browser keeps track of which entry is open. If you do need the state, listen for the toggle event instead of setting open on every render.

/* global.css: :root { interpolate-size: allow-keywords; } */ export function FaqItem({ question, children }) {  return (    <details      name="faq"      className="border-b border-black/10        details-content:h-0 details-content:overflow-clip        open:details-content:h-auto        details-content:transition-[height,content-visibility]        details-content:transition-discrete details-content:duration-300        motion-reduce:details-content:transition-none"    >      <summary className="cursor-pointer py-4 font-medium">{question}</summary>      <div className="pb-4 text-black/70">{children}</div>    </details>  );}
One entry as a React component with Tailwind. The :root line goes into the global CSS.

One element, three standard attributes, six classes. The state stays in the browser.

Share
Written by
Amelie RoesmannCreative direction

We build websites and web apps at Systra Studios in Münster and put the building blocks from that work here. What you read comes from real projects, not from a brochure.

Systra Studios: web design from Münster

Question on top, answer below.
The FAQ sections for it are ready to take.

FAQ sections with an accordion, from a glass panel over an image to a plain list. They open their answers through a button with aria-expanded and animate the height with Framer Motion, so in every browser. If you would rather do without script, switch the list to details with name.

  • One file per component, as source code in your own project.
  • Built with React, TypeScript and Tailwind CSS v4.
  • Questions and answers sit as data at the top of the file.
Browse FAQ sections
FAQ

Frequently asked questions

For an FAQ yes, and usually better than a custom one. summary is keyboard reachable out of the box, Enter and Space open and close the entry, and the open or closed state is passed to screen readers without anyone maintaining aria-expanded. On top of that comes something custom accordions almost never do: the browser's find in page locates text in closed entries and opens them. According to MDN, Chrome has done that since version 97, Firefox since 148 and Safari since 26.2, there with a known bug when scrolling to the match. It still matters that summary holds only text, no links or buttons, because a click on them would toggle the entry at the same time. For patterns that are more than question and answer, such as tabs with arrow keys, details is the wrong fit.

No, not as of November 2026. MDN's browser data lists interpolate-size and the related calc-size function only for Chrome and Edge from version 129, as experimental. caniuse shows no support in Firefox up to version 162 and Safari up to 27.3 and arrives at around 74 percent of global usage in October 2026. That is less bad than it sounds: a browser that does not know the property skips the declaration, and the transition to auto simply does not happen. The accordion still opens and closes correctly, just without motion. If you need the same motion in every browser, there is no way around JavaScript, for instance a library that measures the height.

No. name only makes sure that at most one entry in the group is open. A click on the open entry closes it, and then none is open. That is exactly what happened in a test with Chrome 153, and the browser did not keep two entries with open in the markup either: only the first stayed open. If you always need exactly one open entry, you are really building tabs rather than an accordion, and tabs need roles of their own and arrow keys, meaning script. For an FAQ, the state with everything closed is fine anyway, because the list of questions is at its shortest then.

For an FAQ in Chrome and Edge no, for the same motion in every browser yes. details with name and the lines of CSS from this guide work in React without state and without an effect, because the browser keeps track of which entry is open. If you still need the state in React, for instance to store it in the URL, read it through the toggle event and do not set open again on every render, otherwise browser and component drift apart. Framer Motion, on the other hand, measures the height itself and so animates in Firefox and Safari too. The price is a dependency, a custom button with aria-expanded and giving up the search in closed entries that details brings along.

Didn't find your question? We're happy to help.

Get in touch