
The elastic button
Buttons, Hover, Text
NewFree
A tooltip in the minimal style, on white: in a sentence three words have a dashed line under them, and resting on one a narrow strip of paper unrolls from it, its little roll running ahead and turning while the words show as the paper opens. Moving to another word the strip rolls itself back up and unrolls there.
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 tooltip that unrolls from the word</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/newsreader@5.3.0/index.css">
<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 tooltip that unrolls from the word: three words of a coffee roaster's note are dotted underneath; resting
on one, a narrow strip of paper unrolls from the word, its little roll running ahead and the words of the
tooltip showing as the paper opens. Moving to another word, the strip rolls itself back up and unrolls there -->
<div class="note" data-note data-autoclic>
<p class="note__label">Mosslane Coffee</p>
<p class="note__text" data-text>
This week’s beans are <button class="term" type="button" aria-describedby="tip-washed" data-term>washed</button>,
<button class="term" type="button" aria-describedby="tip-rested" data-term>rested</button> for ten days
and best as a slow <button class="term" type="button" aria-describedby="tip-pour" data-term>pour-over</button>.
</p>
<p class="note__hint">Rest on an underlined word</p>
<div class="ribbon" data-ribbon aria-hidden="true">
<span class="ribbon__tip" data-tipmark></span>
<span class="ribbon__strip" data-strip>
<span class="ribbon__words" data-words></span>
</span>
<span class="ribbon__curl" data-curl></span>
<span class="ribbon__roll" data-roll></span>
</div>
<span class="tip-text" role="tooltip" id="tip-washed" data-tip>The fruit is washed off before the beans dry.</span>
<span class="tip-text" role="tooltip" id="tip-rested" data-tip>Left to breathe after roasting, for a sweeter cup.</span>
<span class="tip-text" role="tooltip" id="tip-pour" data-tip>Hot water poured by hand over a paper filter.</span>
</div>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>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.
27 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The tooltip that unrolls from the word” from Animorio and fit it into my siteThere is a single strip for all the words: the paper, the roll, the roll’s shadow and the tip. For each word the script puts the text inside it, measures how wide it is and moves it above the word, a little to the left, without letting it leave the note’s box.
A number from 0 to 1 says how open the paper is: the strip is that much of its width, the roll sits on its right edge and its shadow a little behind. GSAP takes the number to 1 with back.out, so the roll goes past and comes back; the roll’s turns slide with the distance covered, and the roll is a little fatter while it still has paper on it.
The text stays still inside the strip, which has overflow hidden: as it widens, the strip uncovers it from the left. The real text for screen readers is in the element with role tooltip, linked to the word with aria-describedby.
The word is a button that looks like text. The dashed line is a background of 3 pixel stripes; while the tooltip is out it becomes a solid red line growing with background-size, and the word rises LIFT pixels on a spring: no change of weight, which would widen the word and shift the line.
The first time the tooltip waits DELAY seconds; if one has just been out the next starts at once. Changing word, the strip rolls back up in REWIND seconds and only then unrolls over the new one. With the keys it shows on focus, Esc puts it away; on a phone a touch opens and closes it.
| Name | File | Default | What it changes |
|---|---|---|---|
DELAY | script.js | 0.35 | The seconds the pointer rests on a word before the first tooltip. |
UNROLL | script.js | 0.8 | The seconds the strip takes to unroll. |
REWIND | script.js | 0.32 | The seconds it takes to roll back up. |
OVERSHOOT | script.js | 1.3 | How far the roll runs past the end before coming back (0 stops dead). |
LIFT | script.js | 1.5 | How many pixels the word rises while its tooltip is out. |
GAP | script.js | 10 | The space between the word and the strip, in pixels. |
For glossaries inside a text: the coffee or wine words on a product page, the terms of a documentation, the items of a contract, the hard words of a lesson. Wherever a word needs one line of explanation without leaving the page.
The sentence narrows with the box and wraps onto more lines; the strip stays inside the note’s box and opens with a touch on a word, another touch or a touch elsewhere closes it.
No running roll: the strip shows already open with a fade and the word stays still.
GSAP 3.15.0, Newsreader (font variabile) 5.3.0, Instrument Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 5.6 KB; the libraries: GSAP 28 KB.
Tested on 24 October 2026
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.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.