
The layered button
Buttons, Hover, Physics
Free
The Upgrade plan button of an app, with a jade chrysalis hanging from a twig in the round end of the pill. The click is the move to Pro: the case darkens and clears until the folded blue wings show inside, splits at its foot, and a butterfly comes out and hangs under the empty case with its wings small, wet and crumpled. It pumps them out in three pushes, dries them with two slow beats and flies out of the pill on a slightly wandering curve, to settle on its top edge, where it opens and closes its wings. The blue is not a painted colour: for every angle the script works out the light reflected by the thin layers of the scales, as in real morphos, so the wings flash sky blue face on and turn deep violet as they tilt.
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 chrysalis button</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the chrysalis button: the Upgrade plan button of an app, with a jade chrysalis hanging from a twig in the round
left end of the pill. A click is the upgrade: the case clears and shows the blue wings folded inside, splits,
and a butterfly climbs out, pumps its wings to full size, dries them and flies out of the pill to settle on its
top edge, opening and closing its wings. Their blue is not a paint: it is worked out from the light reflected
by the thin layers in the scales, so it flashes and turns violet as the wings tilt -->
<div class="chry" data-chrysalis>
<button class="chry__btn" type="button" data-btn data-autoclic>
<span class="chry__fill" aria-hidden="true"></span>
<span class="chry__well" aria-hidden="true"></span>
<span class="chry__faces">
<span class="chry__face" data-face="rest">
<span class="chry__word" data-wide="Upgrade plan" data-rest-text>Upgrade plan</span>
</span>
<span class="chry__face chry__face--busy" data-face="busy" aria-hidden="true">
<span class="chry__shine" data-busy-text>Upgrading…</span>
</span>
<span class="chry__face chry__face--done" data-face="done" aria-hidden="true">
<span class="chry__done" data-done-text>Welcome to Pro</span>
</span>
</span>
</button>
<canvas class="chry__air" aria-hidden="true" data-air></canvas>
<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.
23 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 chrysalis button” from Animorio and fit it into my siteA morpho's scales are stacks of thin layers of chitin and air, and their blue is the light reflected by those layers when the waves come back in step. For every degree of tilt from 0 to 90 the script works out where the first-order peak falls, twice the optical thickness of a pair of layers (70 nanometres of chitin with an index of 1.56, plus the air gap LAYER), each with its own inner cosine from Snell's law; a gaussian band round the peak, wider when the light comes in slanting, is the reflected spectrum. The spectrum is weighed with the eye's colour-matching curves (Wyman, Sloan and Shirley's gaussian fit of the CIE 1931 curves), the XYZ result becomes sRGB with its curve, and colours outside the screen are pulled towards the grey of the same lightness instead of being clipped. Out comes a table of 91 colours: sky blue face on, deep blue, violet, nearly black edge on. With LAYER at 160 the same physics gives green, at 190 gold.
Each wing is a shape of three Bézier curves measured in lengths of the forewing, from the root at the thorax. The butterfly is seen from above: a wing raised φ degrees towards the eye gets shorter by cos φ across, and its colour is the table's at the angle φ, plus or minus the tilt of the light (with opposite signs for the two wings, so one flashes while the other goes dark). The same shape, shrunk towards its root, is the blue inside the black border; a gradient along the wing uses three slightly different angles, because the wing is curved. On top, the veins and the fine rows of the scales. For a wing just out, every point of the shape gets a fixed random shove, times crumple, and a grey veil, times wet: the two fall to zero while the size grows in three pushes.
The way is a Catmull-Rom spline through six points, from the shell up over the pill and down onto its edge, walked at an even speed with a table of lengths (240 samples and a binary search). GSAP carries the point along the way with sine.inOut; on top there is a wander across it, the sum of two sines that dies out at both ends, and a small lift at every wing beat. The head follows the way's tangent, with a sway at half the wing beat, and at the start and the end it turns gently upwards, to leave and land upright. The wings beat BEATS times a second between -24 and 84 degrees, and the beat blends with the still pose through fly.amt.
The chrysalis is a drop of four curves with a gradient from the light at the upper left, the gold line and a gloss; it darkens towards the colour of the well while a blue shape clipped inside it comes into view, then crosses over to the empty shell, pale and open at its foot. It turns on its hook with a damped spring (1.5 swings a second), pushed by the pointer and by the timeline's jerks. Once it sits, the butterfly opens and closes its wings with an envelope that dies down in a second and a half, and the light follows the pointer with an exponential lag, stronger the nearer it is. The time step is capped at 1/30 of a second and split into steps of 1/240.
A GSAP timeline does it all: the chrysalis clearing (one second), the split, the coming out, three pushes, two beats, a flight of 1.7 seconds, the landing; PACE changes its speed with timeScale. The button is a real button: aria-disabled while the butterfly is born and while it flies off, an aria-live region says Upgrading your plan… and Welcome to Pro., and the next click is taken only once the wings have calmed down (6.2 seconds), so the preview's click every 2.8 seconds leaves the butterfly sitting for a whole round. Drawing stops when no value changes: a fingerprint of all the values decides whether to draw again, and the canvas covers the pill and the air above it without ever taking the pointer.
| Name | File | Default | What it changes |
|---|---|---|---|
LABEL | script.js | Upgrade plan | The words at rest. If one of the three is too long for the room, the type gets smaller. |
BUSY | script.js | Upgrading… | The words while the butterfly comes out and flies. |
DONE | script.js | Welcome to Pro | The words once the butterfly has landed; the aria-live region says them too. |
PACE | script.js | 1 | The pace of the whole hatching: 2 takes twice as long, 0.5 half. |
LAYER | script.js | 130 | The air gap between the layers of the scales, in nanometres: 130 is morpho blue, 100 violet, 160 green, 190 gold. The wings' colour comes from here. |
BEATS | script.js | 7 | The wing beats a second in flight. |
SIZE | script.js | 1 | The size of the butterfly. |
TWITCH | script.js | 1 | How hard the chrysalis jerks under the pointer and while it opens. 0 it keeps still. |
For moving to a paid plan in an app or a SaaS: Upgrade plan, Go Pro, Unlock premium, or the end of a free trial. It also suits an action that transforms something (publish, activate, ship) in a product with a warm tone. The upgrade is simulated: in a real app the click opens the payment or calls the server, and the done state waits for its answer; the second click that lets the butterfly fly off is there for the demo, in an app it would lead to the plan page.
The pill is about 210 pixels wide and the butterfly flies over it some forty pixels to the sides: at 390 pixels it all fits, and if a set of words is longer than the room the type gets smaller. A tap makes the chrysalis jerk, squashes the fill and hatches the butterfly; the finger, standing in for the pointer, moves the light on the wings.
No jerks, no flight and no beats: at a click the chrysalis darkens and fades into the empty shell, and the butterfly fades in already sitting on the edge, wings open; Upgrading… and Welcome to Pro fade in. The pill does not swell (under the mouse the fill only lightens a little). Another click fades the butterfly away and brings the chrysalis back, again in a fade.
GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 15 KB; the libraries: GSAP 28 KB.
Tested on 13 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.