Skip to content
animorio
IT
All components

The chat that answers

Chat, Transitions, TextGSAPMediumCompressed weight: Demo 7.2 KBGSAP 28 KBFreeDownload the zip

A chat with Nora, who lets a house by the lake: a message sent flies from where it was written, the box or the suggestion tapped, into its bubble while the others move up; then a small bubble shows Nora writing, with a line that writes itself, and grows into her answer.

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 chat that answers</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mulish@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the chat that answers: a message flies from where it was written into its bubble while the others move up,
         and the answer grows out of the little bubble that shows the other person writing -->
    <section class="chat" aria-label="Chat with Nora" data-chat data-autoclic>
      <header class="chat__head">
        <span class="chat__avatar" aria-hidden="true">N</span>
        <div>
          <h2 class="chat__name">Nora</h2>
          <p class="chat__where">Casa del Lago · usually replies in minutes</p>
        </div>
      </header>
      <div class="chat__thread" data-scroll>
        <div class="chat__log" role="log" aria-live="polite" data-log></div>
      </div>
      <div class="chat__quick" role="group" aria-label="Suggested messages" data-quick></div>
      <form class="chat__composer" data-form>
        <label class="sr" for="chat-input">Message Nora</label>
        <input class="chat__input" id="chat-input" type="text" placeholder="Message" autocomplete="off" autocorrect="off" enterkeyhint="send" maxlength="160" data-input>
        <button class="chat__send" type="submit" aria-label="Send" disabled data-send>
          <svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 19V5.5M6.5 11 12 5.5l5.5 5.5"/></svg>
        </button>
      </form>
    </section>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.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.

24 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 chat that answers” from Animorio and fit it into my site

What it does

On a black background a dark box: at the top the circle with the N, Nora and Casa del Lago · usually replies in minutes; under it, three messages (hers on the left in grey, mine on the right in blue, with Read under the last), a row of suggestions (We arrive around 6, Can we check in early?, Is breakfast included?) and the box Message with a round button. Typing, the button lights up and the arrow rises into it with a bounce. Sending (Enter, the button or a suggestion), the message flies from where it was written to its bubble at the end of the conversation, along a curve, turning blue on the way, while the messages above move up to make room; under it Delivered appears. A moment later Delivered turns into Read and a second tick draws itself, and on the left a small bubble pops up with a wavy line that writes and rubs itself out: Nora writing. Then the bubble grows into the answer, whose words come in one after another. The suggestions used go away and the others slide into place.

How it works

The flight

The new message goes straight into its place, hidden; a copy of it, above everything (the conversation would clip it), starts from where the words were and heads for the real bubble: x and y on two different eases (power2.inOut and power3.out) draw a curve, the background goes from clear to blue, and on every frame the copy measures the bubble again, so it gets there even if the conversation moves meanwhile. On arrival the copy goes and the real bubble shows.

The others move up

Before every new message each message’s place is measured; after it (the conversation has gone down to its end), each starts from where it was and goes back to zero in 0.45 seconds with power3.out. The oldest messages, out of sight, go once there are more than fourteen.

Nora writing

After WAIT[0] seconds the small bubble shows (scale from 0.5 with back.out) with a wavy line: a stroke-dasharray as long as the line and a stroke-dashoffset from +L to −L, so it writes itself and rubs itself out going forward, in a loop. After WAIT[1] seconds the bubble makes way for the answer.

The answer that grows

The answer goes into its place clipped (clip-path inset) to the size of the small bubble, from the corner they share; the clip opens in GROW seconds, with the numbers on a separate object written on every frame (a clip-path tweened as text would jump), while the words come in one after another. The answers are the suggestions’ ones (ANSWERS); to anything else Nora answers OTHER.

Keys, screen readers and the preview

The conversation is a role log region, which screen readers read as it goes, and every message starts with who speaks (You or Nora, hidden from sight); the bubble of someone writing and the status are aria-hidden. The suggestions are buttons, the box is a real form (Enter sends), and if a used suggestion had the focus, it goes to the first one left. A click from a script (the library’s preview) is a pretend guest: it writes a message letter by letter and sends it, or taps a suggestion, and waits for the answer; it never takes the focus.

Values to change

NameFileDefaultWhat it changes
FLIGHTscript.js0.5The seconds a message takes to fly from where it was written to its place.
WAITscript.js[0.5, 1.4]The seconds before Nora starts writing, and how long she writes.
GROWscript.js0.45The seconds the small bubble takes to grow into the answer.
ANSWERSscript.js[['We arrive around 6', 'Perfect, I’ll leave the key in the box by the door.'], …]The suggestions and Nora’s answers.
OTHERscript.js'Noted, thanks! See you this evening.'Nora’s answer to anything else.

Try them in the Playground

When to use it

For a website’s help desk, messages between a guest and their host, a support chat, an assistant with ready answers, the demo of a messaging app.

On phones

The box takes the width of the screen and the row of suggestions scrolls sideways under a finger; the message box is 16 pixels, so Safari on iPhone does not zoom the page, and the keyboard shows its send key (enterkeyhint send).

With reduced motion

The messages appear straight in their places, without flying, and the others move without sliding; the bubble of someone writing stays still, the answer appears whole and the second tick appears without drawing itself.

Pitfalls

  • An element flying inside a scrolling container is clipped at its edges: a copy hung outside flies, above everything, while the original waits hidden in its place.
  • If the destination moves during the flight (the other messages move up), the copy heads for the place measured on every frame, not the one from the start.
  • A button that goes away while it has the focus leaves it on the page, and someone on the keys gets lost: the focus must be handed to a button nearby.
  • A line with a stroke-dasharray equal to its length and a stroke-dashoffset from +L to −L writes itself and then rubs itself out going forward, without going back.

Libraries

GSAP 3.15.0, Mulish (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 7.2 KB; the libraries: GSAP 28 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