Skip to content
animorio
IT
All components

The questions accordion

Accordions, Text, TransitionsGSAPMediumCompressed weight: Demo 4.4 KBGSAP + SplitText 31 KBFreeDownload the zip

Five questions with one answer open at a time: opening one, the plus turns into a cross inside a ring that fills, a dark card lights up behind it and the lines of the answer rise one after another.

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>The questions accordion</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the questions: one open at a time. Opening one, its plus turns into a cross inside a disc that fills, a card
         lights up behind it, the answer opens and its lines rise one after another -->
    <div class="faq" data-faq>
      <div class="faq__item" data-item>
        <h3 class="faq__head"><button class="faq__q" type="button" id="faq-q1" aria-expanded="false" aria-controls="faq-a1"><span class="faq__text">How long does delivery take?</span><span class="faq__icon" aria-hidden="true"><span></span><span></span></span></button></h3>
        <div class="faq__a" id="faq-a1" role="region" aria-labelledby="faq-q1" hidden><p>Orders leave the workshop within two working days. Delivery takes three to five days in Europe and up to ten elsewhere, and you get a tracking link as soon as the parcel moves.</p></div>
      </div>
      <div class="faq__item" data-item>
        <h3 class="faq__head"><button class="faq__q" type="button" id="faq-q2" aria-expanded="false" aria-controls="faq-a2"><span class="faq__text">Can I change or cancel my order?</span><span class="faq__icon" aria-hidden="true"><span></span><span></span></span></button></h3>
        <div class="faq__a" id="faq-a2" role="region" aria-labelledby="faq-q2" hidden><p>Yes, until it ships. Reply to the confirmation e-mail and we will change the size or the address, or cancel it altogether.</p></div>
      </div>
      <div class="faq__item" data-item>
        <h3 class="faq__head"><button class="faq__q" type="button" id="faq-q3" aria-expanded="false" aria-controls="faq-a3"><span class="faq__text">What if it doesn’t fit?</span><span class="faq__icon" aria-hidden="true"><span></span><span></span></span></button></h3>
        <div class="faq__a" id="faq-a3" role="region" aria-labelledby="faq-q3" hidden><p>Send it back within thirty days, unworn, and you get a full refund. A return label is already in the box.</p></div>
      </div>
      <div class="faq__item" data-item>
        <h3 class="faq__head"><button class="faq__q" type="button" id="faq-q4" aria-expanded="false" aria-controls="faq-a4"><span class="faq__text">Do you gift-wrap?</span><span class="faq__icon" aria-hidden="true"><span></span><span></span></span></button></h3>
        <div class="faq__a" id="faq-a4" role="region" aria-labelledby="faq-q4" hidden><p>Every order can be wrapped in recycled paper with a handwritten card. Leave a note at checkout and tell us what to write.</p></div>
      </div>
      <div class="faq__item" data-item>
        <h3 class="faq__head"><button class="faq__q" type="button" id="faq-q5" aria-expanded="false" aria-controls="faq-a5"><span class="faq__text">How should I care for it?</span><span class="faq__icon" aria-hidden="true"><span></span><span></span></span></button></h3>
        <div class="faq__a" id="faq-a5" role="region" aria-labelledby="faq-q5" hidden><p>Wash it cold and inside out, and dry it flat in the shade. It gets softer with every wash.</p></div>
      </div>
    </div>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/SplitText.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.

19 values to change

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “The questions accordion” from Animorio and fit it into my site

What it does

On a black background five questions separated by thin lines, each with a plus inside a ring. Opening a question, the plus turns by 135 degrees into a cross while the ring fills with white, a dark card with round corners lights up behind the row, the answer opens and its lines rise one after another, each from below its own edge. Opening another one, the open one closes at the same time: its lines fade, it folds up and the cross turns back into a plus. Under the mouse a question moves a little to the right. When the page opens the questions come in one after another and the first answer opens.

How it works

The questions

Each question is a button inside a heading, with aria-expanded and aria-controls, and its answer is a region that is hidden at rest. The plus is two bars in a ring made with an inset box-shadow; the card behind the row is a pseudo-element wider than the row, drawn from two CSS variables that GSAP moves (--card-on and --card-scale).

Opening

The answer goes from zero height to its own (height auto, measured by GSAP) in OPEN seconds with power3.inOut. Its lines are cut by SplitText with a mask each and rise from yPercent 110 to zero, LINES seconds one after another. The icon turns by SPIN degrees with back.out and takes the light background and dark bars.

Closing

The lines fade in 0.18 seconds, the height goes back to zero, the icon turns back and the card goes out; at the end the answer is hidden again and SplitText puts the text back as it was. A question opened again halfway through closing starts from the height it has.

Keyboard and screen readers

Enter and Space open and close; the up and down arrows, Home and End go from one question to another. SplitText puts an aria-label with the whole sentence on the paragraph and hides the lines, so screen readers read the answer as before.

Held from the top

The list is held at the top of the page, so opening and closing only moves its bottom; if the window changes while an answer is open, the text goes back whole and wraps by itself.

Values to change

NameFileDefaultWhat it changes
OPENscript.js0.55The seconds of an answer opening (closing takes a little less).
LINESscript.js0.07The seconds between one line of the answer and the next.
SPINscript.js135How far the plus turns as it opens, in degrees: 135 makes a cross.
FIRSTscript.js0The question open when the page opens, from 0; −1 for none.

Try them in the Playground

When to use it

For the frequently asked questions of a shop, a service or an event, for terms of sale or a sheet of details: wherever there are many answers and one is read at a time.

On phones

The questions narrow to the width of the screen and their typeface goes down to 18 pixels; taps open and close like clicks.

With reduced motion

The answers open and close at once, with no rising lines; the cross and the card appear straight away and when the page opens the first answer is already open.

Pitfalls

  • SplitText lines only hold for the width they were cut at: if the window changes the text goes back whole, which is why the answer is cut each time it opens.
  • Opening an answer again while it closes, starting from zero height would jump: it starts from the height it has, and from zero only if it was fully closed.
  • The icon’s colour must be animated between real colours: GSAP cannot interpolate a var() written in a tween, which is why the text colour is read from the variable at the start.
  • The card behind the row is wider than the row itself (with a negative inset): that way the question does not move when the card lights up.

Libraries

GSAP 3.15.0, SplitText (GSAP) 3.15.0, Instrument Sans (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 4.4 KB; the libraries: GSAP + SplitText 31 KB.

Testing

Tested on 3 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: Done

License

Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.

All components