Skip to content
animorio
IT
All components

The hanger button

Buttons, Physics, HoverCanvas, GSAPAdvancedCompressed weight: Demo 18 KBGSAP 28 KBFreeDownload the zip

The Add to bag button of a clothes shop: over a coffee-coloured pill, on a steel rail, a pale blue linen shirt hangs on a beech hanger, and in the end of the pill stands a kraft paper bag. The shirt is truly simulated cloth, point by point, with folds that catch the light: the pointer blows on it and it sways. At a click the hanger slides along the rail to the bag, swings with its inertia and the shirt swings after it; on the way it folds as in a shop, sleeves behind and tail up, the hanger dips and lets it drop into the bag, which gives and springs back: Added · Size M, with Undo. Another click takes it out, unfolds it and hangs it 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 hanger 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 hanger button: the Add to bag of a clothes shop. Over the pill, on a short steel rail, a small linen shirt
         hangs on a wooden hanger; the shirt is simulated cloth (a grid of points held by links) drawn on a canvas with
         the light on its folds, and a paper bag stands in the round end of the pill. The pointer blows on the cloth;
         a click slides the hanger along the rail, folds the shirt and drops it in the bag; another click hangs it up
         again -->
    <div class="hang" data-hang>
      <canvas class="hang__cloth" aria-hidden="true" data-cloth></canvas>
      <button class="hang__btn" type="button" data-btn data-autoclic>
        <span class="hang__fill" aria-hidden="true"></span>
        <span class="hang__faces">
          <span class="hang__face" data-face="rest">
            <span class="hang__word" data-wide="Add to bag · €89" data-rest-text>Add to bag · €89</span>
          </span>
          <span class="hang__face hang__face--busy" data-face="busy" aria-hidden="true">
            <span class="hang__shine" data-busy-text>Adding…</span>
          </span>
          <span class="hang__face hang__face--done" data-face="done" aria-hidden="true">
            <span class="hang__done">
              <svg class="hang__tick" viewBox="0 0 16 16" aria-hidden="true" data-tick><path d="M3.2 8.6l3 3 6.6-7"/></svg>
              <span data-done-text>Added · Size M</span>
            </span>
            <span class="hang__undo" data-undo-text>Undo</span>
          </span>
        </span>
      </button>
      <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.

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

What it does

On a white background a coffee-coloured pill 60 pixels tall, with the words Add to bag · €89 in ivory Mona Sans and, in its round right end, a kraft paper bag with its turned-down top, the creases of its gussets and two handles of twisted paper, the back one darker. Over the pill, on a steel rail with a collar at each end, hangs a beech hanger with its grain and its hook of chromed wire, and on the hanger a pale blue linen shirt with short rolled sleeves: the collar with its two points throwing a shadow, the placket with five shell buttons, the stitched pocket, the rounded hem with its stitching and the weave of the linen. The shirt is not a still picture: it is a grid of points in 3D held together by links, hung by its shoulders from the hanger, and it falls in soft folds from the chest down; each small piece is light or dark as it faces the lamp, with a veil of sheen on the folds that face it. On arrival the hanger swings once. With the mouse near, the pointer blows: the cloth fills and sways, in gusts that run out from it, harder if you move it fast; over the pill the words widen and the fill swells with a bounce. At a click Adding… arrives with a sheen running through it, and the hanger slides along the rail to above the bag: starting it lags and the shirt flutters, stopping it runs on and swings. Meanwhile the shirt folds: the sleeves and the sides turn behind, then the tail comes up behind, and a parcel is left with the collar and the buttons in front. The hanger dips over the bag and lets it go: the folded shirt drops in, the bag gives under the blow and comes back with a small bounce, and the empty hanger rises and swings. The pill says Added · Size M, with a green tick that draws itself and a small Undo pill. Another click brings the hanger down, lifts the shirt out still folded, hooks it back by the shoulders, unfolds it and carries it back along the rail to its place. With the keyboard the focus shows a coffee ring and a breath moves the cloth; Enter or Space put it in the bag. On a phone a finger resting near the shirt blows and a tap puts it in the bag.

How it works

A shirt cut from a grid

The flat shirt is an outline (collar, sloping shoulders, short sleeves, sides, rounded tail) and a grid of 20 by 17 points 2.8 pixels apart: only the cells that touch the outline are kept, about two hundred, with their points. Between the points there are links along the rows, along the columns and across both diagonals of each cell (so the cloth neither stretches nor shears) and a softer pair two points apart, which resists sharp bends. The rest length of every link is measured on the shirt already draped: a few soft folds in depth from the chest down, so hanging still it is never a flat sheet.

Verlet, in fixed steps

Each point has its position now and the one before: its speed is the difference, held back a little by the air, and the forces (gravity, the blowing, the springs of the folding) are added times the square of the step. Then the links are brought back to their length twenty times a step, in fixed steps of 1/120 of a second (the frame capped at 1/30). The points of the shoulders are pinned to the hanger and follow it; the limits are constraints too: the cloth never comes down onto the words of the pill, and in the bag it stays between the walls and above the floor.

The light on the folds

The shirt is painted once on a canvas off screen, four times finer: the linen with its weave of threads, the seams, the pocket, the placket and its buttons, the collar with its shadow; and a second time plain linen, for the wrong side. Every frame the normal of each point (the cross product of its neighbours) gives a shade map and a sheen map as large as the grid: they are laid on the painting, enlarged with smoothing, in multiply and in screen. Then every cell is drawn in two triangles, each with its piece of the painting carried by the affine transform from the three flat points to the three points now, clipped a little wider so no seams show; the cells are sorted by depth and a triangle turned over shows the wrong side.

The hanger is a pendulum

The hanger slides along the rail with a GSAP tween; its acceleration is read every frame (finite differences, filtered) and drives the hanger's angle like a pendulum's hung from the hook: θ'' = −ω0² sin θ − 2ζω0 θ' − SWAY · a / L · cos θ. Starting it lags, stopping it runs on, and the cloth hung by its shoulders follows on its own, lagging more down at the tail.

Folding it and dropping it

Folding is a spring for each point towards its place in the folded shirt, worked out from its flat place: beyond two upright lines the sleeves and the sides turn behind (up to 0.94 of half a turn), then below a level line the tail comes up behind. The sharp bends resist less while it folds, and meanwhile the outer shoulders leave the hanger. When the hanger dips, the parcel passes to a frame that falls on its own with gravity and hits the floor of the bag with a bounce; the springs stay, softer, and the links and the walls crumple it a little. The bag squashes from its floor and comes back with elastic.out.

The words and the states

Three faces on top of each other, as wide as their words: Add to bag · €89 (with an invisible wide copy holding the room of the words that widen), Adding… with a sheen running through it, and Added · Size M with the tick drawing itself through its dash and the small Undo. The button is a real button: aria-disabled while it works, an aria-live region says Adding…, Added · Size M. In your bag. and Removed from your bag., and the aria-label says what the next click will do. The whole cycle fits in the 2.8 seconds between two clicks of the preview.

Values to change

NameFileDefaultWhat it changes
LABELscript.jsAdd to bag · €89The words at rest, with the price.
BUSYscript.jsAdding…The words while the shirt goes into the bag; the aria-live region says it too.
DONEscript.jsAdded · Size MThe words with the shirt in the bag. In a real shop the size chosen goes here.
UNDOscript.jsUndoThe small pill on the right: another click hangs the shirt back.
SLIDEscript.js1The seconds the hanger takes to slide along the rail: shorter, more jolt and more swing.
SWAYscript.js1How far the hanger swings on the start and the stop: 0 it stays upright (the cloth still sways).
BLOWscript.js1How hard the pointer blows on the shirt: 0 not at all, 2 a gust.
DRAPEscript.js1How deep the soft folds of the shirt are as it hangs still: 0 a smooth sheet.

Try them in the Playground

When to use it

For the button that puts a garment in the cart: a clothes shop, for linen and cotton, made-to-measure shirts, workwear or children's clothes, a boutique or a second-hand shop. The hanger suits pages with one product and the size already chosen. It has to be wired to your real cart: here adding is simulated.

On phones

The pill is 296 pixels wide and the component 130 tall: at 390 pixels it fits with room to spare. A finger resting near the shirt blows like the pointer, and a tap on the pill runs the whole round: slide, fold, bag. The sizes stay the computer's.

With reduced motion

The shirt hangs still on the hanger with its drape, the pointer does not blow, the hanger neither slides nor swings, the pill does not swell and the words do not widen (under the mouse the fill only lightens a little). At a click the shirt fades away leaving the hanger empty and Added · Size M fades in; another click brings it back the same way.

Pitfalls

  • With true gravity to scale (a 44 pixel shirt for 70 centimetres) the slide along the rail made the shirt fly almost level: the acceleration matched gravity. A gravity twice as strong, a slide in sine.inOut and a little more air make it flutter without losing its shape.
  • With eight passes over the links a step the hanging cloth stretched by a fifth and nearly touched the pill. Twenty passes keep it to its size and cost little: there are about a thousand links.
  • The folded shirt stayed put over the bag instead of dropping in: the limit that keeps the cloth over the words of the pill also held over the mouth of the bag. Now it holds only left of the bag.
  • With reduced motion the fading shirt showed a grid: every triangle, clipped a little wider, overlapped its neighbour and with transparency the overlaps showed. While it fades the shirt is drawn whole on a layer of its own, which is then laid down transparent.
  • The pointer's blowing at first pushed the whole shirt back, and from the front it seemed to rise flat towards the rail. Now three quarters of the push in depth is a wave going back and forth, and the shirt sways instead of lifting.
  • Undo touched Size M: the pill, 272 pixels wide, was not enough for the tick, the words and the small pill. It is 296 wide.
  • With the shortest slide and the most swing the hanger went right round over the rail, shirt and all. The hook now stops it at 0.62 radians and takes its speed away with a small bounce, as a real hook against its rail.

Libraries

GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.

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

Testing

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