Skip to content
animorio
IT
All components

The yo-yo button

Buttons, Physics, SVGGSAP, CSS onlyAdvancedCompressed weight: Demo 9.3 KBGSAP 28 KBFreeDownload the zip

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.

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 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>

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.

20 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 yo-yo button” from Animorio and fit it into my site

What it does

On a white background an ink-coloured pill 60 pixels tall, with a thread of light along the top and a soft shadow under it; on the left Load more stories in cream condensed Instrument Sans. In the round right end, where the arrow would be, a red lacquered yo-yo 42 pixels across, resting in its socket: the glossy rim with a glint, a dark groove and the ivory cap with two curved blades printed in black. Passing over the pill the words widen, the fill swells with a bounce and the yo-yo slips a few pixels out and turns a little, as under a thumb. At a click the pill says The Sunday Read and Fetching stories and the yo-yo drops under the pill unwinding its cream string, faster and faster and spinning harder and harder, until the string runs out: there it bounces a hair and sleeps, spinning in place, while the string shivers and it sways a little; the print on its cap, too fast for the eye, becomes a set of grey rings. When the stories arrive the pill gives a tug upwards and the yo-yo climbs back up the string, slower and slower, until it drops into its socket with a small knock that jolts the pill, which says 12 more stories · 24 on the page now. The next click throws it again and the count goes up. With the keyboard the focus shows a red ring and lets the yo-yo slip out; Enter or Space throw it. On a phone a tap throws it.

How it works

The yo-yo in an SVG

A 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.

A spool rolling on its string

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).

The climb

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 pendulum and the string

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.

The states

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.

Values to change

NameFileDefaultWhat it changes
LABELscript.jsLoad more storiesThe words at rest.
SECTIONscript.jsThe Sunday ReadThe small line while the stories arrive: the section they come from.
LOADINGscript.jsFetching storiesThe words while the yo-yo sleeps; the aria-live region says them too.
PER_PAGEscript.js12How many stories each click adds: the pill says the number and the total on the page.
WAITscript.js1.4The seconds the stories take to arrive: the yo-yo sleeps meanwhile. In a real site it is the time the server takes to answer.
HOLDscript.js2.2The seconds the pill says how many stories arrived before it goes back to Load more stories.
DROPscript.js118How much string there is, that is how far the yo-yo drops under the pill, in pixels.
THROWscript.js260How hard the yo-yo is thrown, in pixels a second: harder, it gets down sooner and spins more.
SPIN_LOSSscript.js0.3How fast the sleeping yo-yo slows down: 0 it spins for ever.

Try them in the Playground

When to use it

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.

On phones

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.

With reduced motion

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).

Pitfalls

  • Three blades printed on the cap looked like a fan. Now there are two curved blades turning the same way, like a yo-yo's print.
  • The string's knot drawn as a pale little ring on the pill looked like a dot. Now the string comes out of the middle of the dark socket the yo-yo rests in.
  • The blurred cap of a fast-spinning yo-yo had a narrow dark ring and a light middle, and the sleeping yo-yo looked like an eye. Now the ring is wider and lighter, and the cap stays ivory with a grey veil, like a print going round.

Libraries

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.

Testing

Tested on 19 October 2026

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

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