
The needle gauge
Counters, Physics, SVG
NewFree
A magazine's Load more, with a red lacquered yo-yo in the round end of the pill, where the arrow would be. At a click the yo-yo is thrown: it drops out of the pill unwinding its string, sleeps at the bottom spinning while the stories arrive (past a certain speed the print on its cap blurs into rings, as the eye sees it), and when they are in the pill gives a tug and the yo-yo climbs back winding up the string into its place. The fall, the sleep and the climb are the real physics of a spool rolling on its own string.
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 yo-yo button</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the yo-yo button: the Load more of a magazine, with a lacquered yo-yo in the round right end of the pill, where
the arrow would be. A click throws it: it drops out of the pill unwinding its string, sleeps at the bottom,
spinning, while the stories load, and when they arrive the pill gives a tug and it climbs back into its place -->
<div class="yoyo" data-yoyo>
<div class="yoyo__unit">
<button class="yoyo__btn" type="button" data-btn data-autoclic>
<span class="yoyo__fill" aria-hidden="true"></span>
<span class="yoyo__faces">
<span class="yoyo__face" data-face="rest">
<span class="yoyo__word" data-wide="Load more stories" data-rest-text>Load more stories</span>
</span>
<span class="yoyo__face yoyo__face--two" data-face="busy" aria-hidden="true">
<span class="yoyo__small" data-busy-small>The Sunday Read</span>
<span class="yoyo__big" data-busy-text>Fetching stories</span>
</span>
<span class="yoyo__face yoyo__face--two" data-face="done" aria-hidden="true">
<span class="yoyo__big" data-done-text>12 more stories</span>
<span class="yoyo__small" data-done-small>24 on the page now</span>
</span>
</span>
</button>
<!-- the yo-yo and its string, drawn by script.js; the pointer goes through them to the button -->
<svg class="yoyo__art" viewBox="-50 -40 100 250" aria-hidden="true" data-art></svg>
</div>
<p class="sr" aria-live="polite" data-live></p>
</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.
20 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 yo-yo button” from Animorio and fit it into my siteA single SVG lies over the right end of the pill and reaches below it (pointer-events: none, so the click reaches the button); its origin is the middle of the end, where the string is tied. The yo-yo's parts are drawn once: the lacquered disc with a radial gradient, the groove, the ivory cap with its two printed blades, the glints that do not turn because the light does not turn. Every frame only the yo-yo's position, the cap's rotation, the opacity of its blurred copy and the string's path change.
The yo-yo falls with only a share of gravity, because most of the fall goes into the spin: a = g / (1 + I / m r²), and with the string wound on an axle much thinner than the disc that comes to 340 pixels a second a second instead of 2200. The spin is the string's speed over the axle: ω = v / r, with r = 2.6 pixels. The throw gives a starting speed (THROW); when the string runs out the yo-yo bounces on the string's stretch and sleeps, and the spin slows slowly (SPIN_LOSS).
At the tug the string bites the axle and the spin rolls the yo-yo back up: the climbing speed is the one that takes it to the top with a little to spare, √(2 · a · length), and it slows with the same acceleration; meanwhile the spin follows the speed, ω = v / r. At the top the yo-yo drops into its socket with a small knock, and the pill's fill squashes and springs back.
The yo-yo also swings, as a pendulum as long as the string that is out: θ'' = −(g / L) sin θ, damped; the throw leaves it a little off the vertical, so it sways slowly as it sleeps. The string is a quadratic curve from the knot to the axle; while the yo-yo sleeps its control point shivers with the spin. Above 14 turns a second the cap with its blades gives way to a cap blurred into grey rings, as a thing spinning too fast is seen.
Three faces on top of each other, as wide as their words (at rest, loading, added); the pill is measured once on the widest, with the highest number it can say. The button is a real button with aria-disabled while the yo-yo is out, an aria-live region that says Fetching stories… and then 12 more stories. 24 on the page now., and an aria-label that says what the click does. The whole cycle takes about 2.3 seconds, less than the 2.8 between two clicks of the preview: each click loads a page.
| Name | File | Default | What it changes |
|---|---|---|---|
LABEL | script.js | Load more stories | The words at rest. |
SECTION | script.js | The Sunday Read | The small line while the stories arrive: the section they come from. |
LOADING | script.js | Fetching stories | The words while the yo-yo sleeps; the aria-live region says them too. |
PER_PAGE | script.js | 12 | How many stories each click adds: the pill says the number and the total on the page. |
WAIT | script.js | 1.4 | The seconds the stories take to arrive: the yo-yo sleeps meanwhile. In a real site it is the time the server takes to answer. |
HOLD | script.js | 2.2 | The seconds the pill says how many stories arrived before it goes back to Load more stories. |
DROP | script.js | 118 | How much string there is, that is how far the yo-yo drops under the pill, in pixels. |
THROW | script.js | 260 | How hard the yo-yo is thrown, in pixels a second: harder, it gets down sooner and spins more. |
SPIN_LOSS | script.js | 0.3 | How fast the sleeping yo-yo slows down: 0 it spins for ever. |
For the Load more of a magazine, a blog, an archive of articles, a gallery of projects or a catalogue, and for any button that asks the server for more and waits (Refresh, Sync, Fetch). The button fakes the loading: in a real site the click asks for the next page, the yo-yo sleeps until the server answers and climbs back when the stories are on the page.
The pill is about 250 pixels wide and the yo-yo drops 120 under its right end: at 390 pixels it fits, with the string always on screen. A tap throws it; the yo-yo keeps its size.
The yo-yo does not fall or spin: while the stories arrive it dims in its socket, and comes back to full colour when they are in. The words fade in, the pill does not swell and the words do not widen (under the mouse the fill only lightens a little).
GSAP 3.15.0, Instrument Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 9.3 KB; the libraries: GSAP 28 KB.
Tested on 19 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.