Skip to content
animorio
IT
All components

The domino button

Buttons, Physics, 3DCanvas, GSAPAdvancedCompressed weight: Demo 12 KBGSAP 28 KBFreeDownload the zip

The Run workflow button of an automation tool: a graphite pill seen from above, with a row of domino tiles standing on it in a gentle curve. Pressed, the first tile falls and the chain reaction runs across the button, faster and faster, one tile after the other, while the label follows the steps of the workflow until Workflow complete. The tiles are truly simulated rigid bodies, turning on their edge and leaning on one another; then they stand up again backwards, like a film rewound.

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 domino button</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the domino button: the Run workflow button of an automation tool, a graphite pill seen from above with a row
         of tiles standing on it in a gentle curve. Pressed, the first tile falls and the chain runs across the pill,
         one step of the workflow after the other -->
    <div class="domino" data-domino>
      <div class="pill" data-pill>
        <canvas class="pill__scene" aria-hidden="true" data-scene></canvas>
        <!-- the words lie on the pill's top, in its perspective: real text, laid there by the script -->
        <span class="pill__label" aria-hidden="true" data-label>
          <span class="pill__icon" data-icon><svg viewBox="0 0 24 24"><path d="M8 5.6v12.8c0 .8.9 1.3 1.6.8l9.4-6.4c.6-.4.6-1.2 0-1.6L9.6 4.8C8.9 4.3 8 4.8 8 5.6z"/></svg></span>
          <span class="pill__word" data-word>Run workflow</span>
        </span>
        <!-- the real button: a transparent area over the pill -->
        <button class="pill__hit" type="button" aria-label="Run workflow" aria-describedby="domino-note" data-hit data-autoclic></button>
      </div>
      <p class="note" id="domino-note"><span data-steps>4 steps</span> · <span data-last>last run 2 hours ago</span></p>
      <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.

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

What it does

On a white background a graphite pill, thick as a small slab, seen three quarters from above, its edge catching the light and a soft shadow underneath. On the front of the pill, laid in its perspective, the label Run workflow with a play triangle; behind it, a row of fifteen ivory tiles standing in a gentle curve, with their shadows on the top. Below, the grey line 4 steps · last run 2 hours ago. Moving the mouse over the pill, its top brightens a little and the tiles near the pointer tremble, more when the mouse moves fast. Pressed, the pill sinks a few pixels and the first tile is pushed: it hesitates, tips and falls onto the second, which falls onto the third, and the chain runs to the right faster and faster, the fallen tiles leaning on one another like shingles. Each tile, as it lies down, shows its coloured back, from violet to green along the row; meanwhile the label goes through Fetching new orders, Enriching contacts, Updating the CRM and Posting the summary. When the last tile lands the label becomes Workflow complete with a green tick and the line below says last run just now. A few seconds later the label says Resetting and the tiles stand up again backwards, from the last to the first, like a film rewound; then Run workflow is back. Pressing again once the chain is down, the row stands up and runs again.

How it works

A tile, an inverted pendulum

Each tile is a rigid body turning on the front edge of its base. Its centre of mass sits at half its height and half its thickness: its height above the top, (t/2)·sin a + (h/2)·cos a, is the tile's energy, and the tile stays up until its angle passes arctan(t/h), then gravity makes it fall faster and faster, like an inverted pendulum. The finger's push is a starting speed PUSH times the one just enough to tip it.

The contact, from geometry

A fallen tile leans on the next: the angle at which it does is the one that puts its top edge exactly on the other's back face, found by bisection. So the whole fallen part of the chain depends on one angle only, the front tile's, and when the front tile lies down on the top the others stop like shingles, each on the next.

The chain as one body

The falling part has an energy and an inertia that change with the angle: the inertia is the sum of each tile's times the square of how much it turns when the first one turns, worked out with finite differences. The equation of motion comes from the Lagrangian, q″ = (−V′ − I′·q′²/2) / I, integrated in ten steps per frame with the step capped at 1/30 of a second. At every hit the new tile joins the body and the chain keeps KEEP of its energy: that is why it starts slowly, speeds up and then runs at a steady speed, like a real chain.

The drawing in 3D

The pill, the tiles and the shadows are a small model drawn on a canvas every frame: a camera raised 56 degrees projects the points with a touch of perspective, the faces turned away (told by the way they wind on the screen) are not drawn, the tiles go from the farthest to the nearest, and each face takes its light from a lamp. The shadows are the eight corners of each tile projected onto the top along the light, wrapped in a convex hull and all drawn together on a separate canvas, so where they overlap they do not get darker.

The label on the pill and the rewound film

The label is real HTML text, laid on the pill's top with a matrix() made of two projected vectors, and it sinks with it. During the fall the script records the angles of every frame: the return is that recording played backwards in REWIND seconds, so the tiles stand up exactly as they fell, from the last to the first. When nothing moves the canvas is not redrawn.

Values to change

NameFileDefaultWhat it changes
TILESscript.js15How many tiles stand in the row (the pill grows longer with them).
GAPscript.js23The distance from one tile to the next, in pixels (a tile is 54 tall).
GRAVITYscript.js950The pull on the tiles, in pixels per second squared: less is slow motion.
PUSHscript.js1.25How hard the press pushes the first tile (1 = just enough to tip it).
KEEPscript.js0.66The share of the energy the chain keeps at every hit.
CURVEscript.js14How much the row bends, in pixels.
DONEscript.js2.8The seconds the button says Workflow complete before the tiles stand up again.
REWINDscript.js1.2The seconds of the rewind.
TREMBLEscript.js1How much the tiles near the pointer tremble.
STEPSscript.js['Fetching new orders', 'Enriching contacts', 'Updating the CRM', 'Posting the summary']The jobs of the workflow the label goes through while the chain runs.

Try them in the Playground

When to use it

For the button that starts something made of steps in a row: an automation workflow, a pipeline, an import, an email sequence. The chain says without words that one step sets off the next. It works on its own, at the spot on the page where the main action is launched.

On phones

The drawing scales to the width of the screen (at 390 pixels the pill is about 350 wide) and nothing spills over. A tap presses the pill, which sinks under the finger; the trembling as the pointer passes is for the mouse only.

With reduced motion

Nothing falls: the standing row fades into the fallen one, with its coloured backs, and the label goes straight to Workflow complete; the return is the same fade backwards. The pill does not sink and the tiles do not tremble.

Pitfalls

  • With the tile turning on the middle of its base, the chain never came to rest as shingles: the fallen tiles slid into one another. The pivot is the front edge, and the resting tiles, when they tremble, turn on the middle only by a few hundredths of a radian.
  • Simulating every tile on its own, with the hits as bounces, made the whole row jitter and sometimes a tile went through another. With the fallen tiles tied by geometry the falling part has a single degree of freedom, and the physics is stable even with a large step.
  • With no energy lost at the hits the chain sped up endlessly until it was a flash: with KEEP at two thirds it reaches a steady speed, like a real one.
  • The canvas blur() filter on the shadows, every frame, froze the first frame for two seconds on a computer without a graphics card: the shadows are now a single layer at half opacity, and the pill's soft shadow on the page is drawn once for each size.
  • With the camera turned the other way, the standing tiles already showed their coloured backs and the surprise of the fall was gone: the camera looks at the ivory faces, and the colour appears only when a tile lies down.
  • The label animated with a blur filter on text transformed in perspective slowed down every change of step: it changes with a plain fade.

Libraries

GSAP 3.15.0, Geist (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 12 KB; the libraries: GSAP 28 KB.

Testing

Tested on 5 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