Accordion
An example of an accordion component using Motion. Animate accordion content using height: auto and accessible markup. Uses focus events and shared layout animations for keyboard accessibility.
Tutorial
Introduction
The Accordion example shows how to build a fully accessible accordion component with smooth animations. It uses the press event handler from Motion to detect button clicks and the animate function to create smooth height transitions, content fade effects, and chevron rotations.
One of the most challenging aspects of building accordions is animating to height: auto. While browsers now support this via interpolate-size: allow-keywords, browser support is still limited. Motion makes this easy by automatically calculating the final height and creating smooth animations that work across all browsers.
Get started
Let's start with the basic HTML structure for an accordion. We'll create three sections, each containing a button header and collapsible content area:
<div class="accordion">
<section>
<h3>
<button
id="item1-button"
aria-expanded="false"
aria-controls="item1"
class="big"
>
<span>Question 1</span>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m6 9 6 6 6-6" />
</svg>
<div class="focus-ring"></div>
</button>
</h3>
<div
id="item1"
aria-labelledby="item1-button"
class="accordion-content"
>
<div>
<p class="small">Answer 1</p>
</div>
</div>
<hr />
</section>
<section>
<h3>
<button
id="item2-button"
aria-expanded="false"
aria-controls="item2"
class="big"
>
<span>Question 2</span>
<!-- Copy SVG from above -->
<div class="focus-ring"></div>
</button>
</h3>
<div
id="item2"
aria-labelledby="item2-button"
class="accordion-content"
>
<div>
<p class="small">Answer 2</p>
</div>
</div>
<hr />
</section>
<section>
<h3>
<button
id="item3-button"
aria-expanded="false"
aria-controls="item3"
class="big"
>
<span>Question 3</span>
<!-- Copy SVG from above -->
<div class="focus-ring"></div>
</button>
</h3>
<div
id="item3"
aria-labelledby="item3-button"
class="accordion-content"
>
<div>
<p class="small">Answer 3</p>
</div>
</div>
<hr />
</section>
</div>
<style>
/** Copy styles from example source code */
</style>
The markup follows accessibility best practices. Each button has aria-expanded to indicate whether the content is visible, and aria-controls to link it to the content area. The content uses aria-labelledby to reference its button.
Note that the .accordion-content starts with height: 0 and opacity: 0 on the inner div, hiding the content by default.
Related examples
Latest in JavaScript
Unlock all 400+ examples
- Source code for every Plus example.
- Provide examples direct to your agent via Motion's MCP.
- Lifetime access to new examples and APIs.








