
The needle gauge
Counters, Physics, SVG
NewFree
A download that opens its own button: the words make room, the teeth of a zipper appear along the middle and the pull runs from left to right with the progress; behind it the two sides of the cloth part on the orange lining, with the percentage travelling in the opening, and the tab swings each time the pull starts and stops. At the end the sides fall open on the saved file, and a click or a moment zips it all back.
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 zipper button</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/parkinsans@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the zipper button: a download that unzips the button as the file comes in; the pull runs along with the
progress and swings as it starts and stops, and at the end the two sides fall open on the saved file -->
<div class="zip" data-zip data-autoclic>
<button class="zip__btn" type="button" aria-label="Download .zip, 2.4 MB" data-btn>
<svg class="zip__art" aria-hidden="true" data-art></svg>
<span class="zip__label" aria-hidden="true">
<span class="zip__name" data-part>Download .zip</span>
<span class="zip__size" data-part>2.4 MB</span>
</span>
<span class="zip__done" aria-hidden="true" data-done>
<svg class="zip__check" viewBox="0 0 24 24"><path d="M5 12.6l4.3 4.3L19 7.2" pathLength="1" data-check/></svg>
<span class="zip__saved">
<span class="zip__saved-name">Saved to Downloads</span>
<span class="zip__saved-file">animorio.zip</span>
</span>
</span>
</button>
<p class="zip__hint"><span data-hint>14 files, ready to unzip</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>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 zipper button” from Animorio and fit it into my siteThe button is an SVG redrawn every frame from a few numbers that GSAP moves (where the pull is, how far the zipper may open, how much of the teeth shows, how far the sides have fallen). Each side is a path: the outer edge of the pill, sampled closely round the rounded ends and every 6 pixels in between, then the edge of the zipper; the cloth is a pattern of diagonal lines, and the stitches run 6 pixels inside the edge.
At each x, each side moves off the middle by GAP/2 times smoothstep((pull − x) / SPREAD): just behind the pull the teeth start to come apart, SPREAD pixels further back they are fully open, in front of the pull they stay shut. The teeth, one every 4.6 pixels, belong in turn to the top side and the bottom one, and when shut they sit between each other.
The pretend progress is a timeline of six stretches that together last SPEED seconds, each with sine.inOut: the pull sets off and stops like the pieces of a file coming in. The percentage sits SPREAD + 6 pixels behind the pull, where the opening is full, and is clipped by the shape of the button.
The tab is a pendulum: every frame its acceleration is a spring pulling it back down, a damping, and the push of the pull's acceleration (measured from the difference between two speeds) times SWING. So it swings when the pull starts and when it stops, and when the mouse arrives on the button.
At the end the two sides move away by 0.85 times the height with power3.in and fade over the lining, where the tick draws itself with stroke-dashoffset. Zipping back, the same wedge follows the pull as it returns. A click from a script (the library's preview) downloads and, once the file is saved, zips it back; it never cancels halfway.
| Name | File | Default | What it changes |
|---|---|---|---|
SPEED | script.js | 2.6 | The seconds the pretend download takes. |
GAP | script.js | 24 | How far apart the two sides of the zipper go, in pixels. |
SPREAD | script.js | 70 | How many pixels behind the pull the zipper takes to open all the way. |
SWING | script.js | 1 | How much the pull's tab swings when the pull starts and stops. |
DONE | script.js | 2.2 | The seconds the button says Saved before it zips itself back. |
For the button that downloads an archive, a price list, a press kit or a project's files: wherever the wait for a download can become a small show, and wherever a zipper truly belongs (clothing, bags, travel).
The button is 320 pixels wide, or the screen minus 48, and the zipper is redrawn to the real size at every resize; at a touch it gives a little as with the mouse, and the tab swings for the mouse arriving, not for the finger.
The download still shows, with the pull moving steadily without fits and starts, and the percentage; the words vanish without sliding, the tab does not swing, at the end the saved file is there at once without the sides falling, and zipping back is immediate.
GSAP 3.15.0, Parkinsans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.1 KB; the libraries: GSAP 28 KB.
Tested on 12 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.