You might not need JavaScript - Accordions & Collapsibles

Less complexity & more accessibility with the power of native HTML & CSS

Table of Contents

Intro

Most accordions & collapsibles on the web these days are either way too complex or not accessible at all. That’s mainly due to the fact that it’s a pretty widely used component that’s often just written once and then reused over and over or directly imported from a component library without further investigating the code. It’s often up until the point when you have to add custom functionality or styles that developers realize how complex or inaccessible their implementations really are.
Luckily a better solution has been around for quite some time, and it’s gotten even more additions to it’s functionality in the last few months. So let’s dive right in and explore the modern way of implementing accordions & collapsibles.

Collapsibles - Details & Summary

When talking about accordions & collapsibles, the first things that come to mind are the <details> and <summary> elements. They form the baseline when talking about native collapsible functionality. Since they have been supported for almost a decade, there is no need to worry about browser support.

The most trivial implementation looks like this:

<details>
  <summary>I'm a summary for the collapsed content</summary> 
  <p>Hey there! 👋🏻 I'm the content</p>
</details>
I’m a summary for the collapsed content

Hey there! 👋🏻 I’m the content

While not the prettiest thing to look at, it still provides the most basic functionality for a collapsible. The <summary> element serves as the headline as well as the trigger for the collapsible content, whilst the <details> element is the container for the content to be collapsed. Now, let’s start to build on top of this basic implementation and add some additional functionality.

Auto-Collapsing - The Accordion Case

Now that we have a basis for a single collapsible, let’s take a look at how to create an accordion. An accordion usually is a collection of collapsibles, where only one can be open at a time, automatically closing the currenly open one when a new one is opened.

This feature is actually quite new to the <details> element, having been added in the last few months. It can therefore be considered a progressive enhancement, as it doesn’t break the basic functionality of the element in older browsers, but at the same time provides a better user experience for users with more modern browsers.

The implementation is really straightforward, as it is already known from the <input type="radio"> HTML element, which acts in a similar fashion in terms of selectability. Providing a name attribute to all <details> elements that should be grouped will make them act as a group, where only one can be open at a time, similar to how radio buttons work.

<details name="accordion">
  <summary>I'm Accordion-Item No.1</summary>
  <p>Hey there! 👋🏻 I'm the content 1</p>
</details>
<details name="accordion">
  <summary>I'm Accordion-Item No.2</summary>
  <p>Hey there! 👋🏻 I'm the content 2</p>
</details>
<details name="accordion">
  <summary>I'm Accordion-Item No.3</summary>
  <p>Hey there! 👋🏻 I'm the content 3</p>
</details>
I’m Accordion-Item No.1

Hey there! 👋🏻 I’m the content 1

I’m Accordion-Item No.2

Hey there! 👋🏻 I’m the content 2

I’m Accordion-Item No.3

Hey there! 👋🏻 I’m the content 3

Now on to the last part and finally add some styles and animations to finish the job.

Animating Collapsibles Properly

When it comes to animating details and summary, there are two hurdles we have to overcome.

Fortunately, both of these problems can be solved with native CSS these days and we therefore still don’t need to rely on JavaScript.

Animating discrete properties

When we talk about discrete properties in a CSS context, we’re talking about properties whose values are not additive, and interpolation swaps directly from the start to the end value of an animation. On the other hand, when a propertys values are additive, it means that the value can be interpolated between the start and end value of the animation, thus creating a smooth animation.

The most common example of a discrete property is display, which can’t be interpolated, so it jumps directly from the start of the animation to the end of the animation at the 50% mark.

Fortunately, as mentioned earlier, we can opt-in to discrete property transitions by setting transition-behavior: allow-discrete on the element we want to animate. This way the browser will override it’s default behavior and instead flip the value at the 0% or 100% mark of the animation, depending on the final value. The opt-in is necessary to prevent legacy browsers from breaking their animation behavior.

Size interpolation

Since we are already talking about interpolation. Let’s take a look at size interpolation. In the past, it was not possible to animate to intrinsic size values. This means that you couldn’t animate to e.g. auto or min-content with pure CSS. This has changed with the introduction of the `interpolate-size’ property, which allows us to opt-in to so-called keyword size interpolations.

Similar to discrete property animations we set interpolate-size: allow-keywords on the element we want to animate. This way we can tell the browser to calculate the size of the element at the start and end of the animation and interpolate the size between these two values. IMPORTANT ─ It is not possible to transition between two intrinsice size values, one, either start or end needs to be of type <length-precentage>.

Putting it all together

Now that we know how to animate discrete properties and sizes, let’s put it all together and create a simple slide animation for our collapsibles.

<details name="accordion">
  <summary>I'm Accordion-Item No.1</summary>
  <p>Hey there! 👋🏻 I'm the content 1</p>
</details>
<details name="accordion">
  <summary>I'm Accordion-Item No.2</summary>
  <p>Hey there! 👋🏻 I'm the content 2</p>
</details>
<details name="accordion">
  <summary>I'm Accordion-Item No.3</summary>
  <p>Hey there! 👋🏻 I'm the content 3</p>
</details>
I'm Accordion-Item No.1

Hey there! 👋🏻 I'm the content 1

I'm Accordion-Item No.2

Hey there! 👋🏻 I'm the content 2

I'm Accordion-Item No.3

Hey there! 👋🏻 I'm the content 3

Let’s dive into the code and see what’s happening here.
First of all, we only enable animations if the user has not set their system to prefer reduced motion. This is an accessibility best practice, it respects the user’s preference and doesn’t force animations on them.
We then opt-in to size interpolation and discrete transitions. We also set block-size: 0 and overflow-y: clip to allow for a smooth transition between the open and closed states.
After that we define the properties we want to animate and the transition duration. The content-visibility property is set by the browser itself when the accordion is opened, therefore we don’t need to specify the final value. The block-size on the other hand needs to be set to auto when details` element is open.

Remember both content-visibility and block-size: auto are only animatable because we opted-in first.

If for some reason you don’t see the animation, make sure you don’t have the Reduced Motion preference enabled. If it still doesn’t work, keep in mind that both of these features are fairly new and may not be supported in all browsers. Like the accordion functionality, the animation can be considered a progressive enhancement because it doesn’t break the basic functionality in older browsers, but provides a better user experience in more modern browsers.

Summary

Collapsibles & accordions are much easier to implement in 2025 than they were a few years ago. With the introduction of the <details> and <summary> elements, we now have a native way to create collapsibles without the need for JavaScript.
The addition of the name attribute to the <details> element allows us to group them together and create an accordion. And with the introduction of content-visibility and interpolate-size, we can now animate the opening and closing of collapsibles with pure CSS.

With a bit of additional styling your collapsible fit’s right into your design system and is accessible to everyone. No need for complex JavaScript solutions or libraries, just plain HTML and CSS.

<details name="group1">
  <summary>
    <span>Accordion 1</span>
    <svg
      aria-hidden="true"
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 407 407">
      <path d="M386 92 204 274 21 92 0 113l204 203 203-203z"></path>
    </svg>
  </summary>
  <div class="content">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua.
  </div>
</details>

<details class="accordion" name="group1">
  <summary>
    <span>Accordion 1</span>
    <svg
      aria-hidden="true"
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 407 407">
      <path d="M386 92 204 274 21 92 0 113l204 203 203-203z"></path>
    </svg>
  </summary>
  <div class="content">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. est laborum.
  </div>
</details>

<details class="accordion" name="group1">
  <summary>
    <span>Accordion 1</span>
    <svg
      aria-hidden="true"
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 407 407">
      <path d="M386 92 204 274 21 92 0 113l204 203 203-203z"></path>
    </svg>
  </summary>
  <div class="content">
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
    tempor incididunt ut labore et dolore magna aliqua. est laborum.
  </div>
</details>
Accordion 1
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Accordion 1
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. est laborum.
Accordion 1
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. est laborum.