Skip to content
animorio
IT
All components

The zipper button

Buttons, SVG, PhysicsGSAPAdvancedCompressed weight: Demo 7.1 KBGSAP 28 KBFreeDownload the zip

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.

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

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

What it does

On a white background a pill button of indigo cloth with dashed stitches along the edge; on the left the brass pull of a zipper, with its tab hanging, and the words Download .zip with 2.4 MB; below, the line 14 files, ready to unzip. As the mouse arrives the tab swings. Clicking, the words slide away to the right, the brass teeth appear from the left along the middle of the button and the pull sets off to the right in fits and starts, the way the pieces of a file arrive: behind it the two sides of the cloth, each with its tape and its teeth, part like a wedge and underneath the orange lining shows, with the white percentage following it in the opening. The tab swings each time the pull starts and stops. At the end the two sides fall open upwards and downwards and fade, the pull disappears and on the lining a tick draws itself, with Saved to Downloads and animorio.zip; the line says Click to zip it back. After a moment, or with a click, the sides come back, the pull runs back to the left closing the zipper, the teeth hide and the words return. Clicking during the download zips it back at once and the line says Download cancelled.

How it works

The cloth redrawn

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

The wedge behind the pull

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 download in fits and starts

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 as a pendulum

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.

The end, zipping back and the preview

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.

Values to change

NameFileDefaultWhat it changes
SPEEDscript.js2.6The seconds the pretend download takes.
GAPscript.js24How far apart the two sides of the zipper go, in pixels.
SPREADscript.js70How many pixels behind the pull the zipper takes to open all the way.
SWINGscript.js1How much the pull's tab swings when the pull starts and stops.
DONEscript.js2.2The seconds the button says Saved before it zips itself back.

Try them in the Playground

When to use it

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

On phones

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.

With reduced motion

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.

Pitfalls

  • At rest the stretch left of the pull is still behind it: without a value that keeps the zipper shut (open at 0) a sliver of lining showed near the edge.
  • An opacity set in the CSS is lost when GSAP brings the element back to opacity 1: the 2.4 MB is faint through its colour (color-mix), not through opacity.
  • The percentage must stay inside the pill: it has a clip-path with the button's shape, or at the start, while it is still left of the edge, it would show outside.
  • The drawing's colours come from the CSS (fill and stop-color in the classes, with the variables): written as attributes by the script they would not follow variables changed live.
  • The pull's speed is measured from one frame to the next: the step must be capped at 1/30 of a second, or after a tab left in the background a jump in time would give the tab a huge push.

Libraries

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.

Testing

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