Skip to content
animorio
IT
Back to the library

The bead curtain

Hover, PhysicsCanvas, GSAPAdvancedCompressed weight: Demo 11 KBGSAP 28 KBFreeDownload the zip

A curtain of strands of wooden, glass and shell beads in front of the door of a beach kiosk: brushing it with the pointer the strands swing like pendulums, knock into each other and slowly calm down, and the sunset drawn by the beads bends. A click walks through it.

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>Bead curtain</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage" data-stage>
    <!-- the front of a little beach kiosk: the painted sign, the doorway and the sand -->
    <header class="sign" data-sign>
      <p class="sign__line">Beach kiosk on the north dune</p>
    </header>

    <div class="door" data-door>
      <!-- inside, behind the curtain: the title and the menu board -->
      <div class="inside" data-inside>
        <div class="inside__glow" data-glow aria-hidden="true"></div>
        <h1 class="inside__title" data-title>Driftwood Shack</h1>
        <p class="inside__line" data-line>Cold drinks, grilled fish and a hammock in the shade.</p>
        <p class="inside__board" data-board>Open till sunset</p>
      </div>
      <div class="door__frame" aria-hidden="true"></div>
    </div>

    <!-- a surfboard leaning on the wall and a potted agave, drawn by hand -->
    <svg class="prop prop--board" viewBox="0 0 60 260" aria-hidden="true" focusable="false" data-board-prop>
      <path class="board__body" d="M30 4 C48 40 54 120 50 200 C48 236 40 254 30 256 C20 254 12 236 10 200 C6 120 12 40 30 4 Z"/>
      <path class="board__stripe" d="M14 120 C24 116 36 116 47 120 L47 132 C36 128 24 128 13 132 Z"/>
      <path class="board__line" d="M30 14 L30 246"/>
    </svg>
    <svg class="prop prop--plant" viewBox="0 0 120 150" aria-hidden="true" focusable="false" data-plant>
      <g class="plant__leaves" data-leaves>
        <path d="M60 96 C52 70 40 44 20 28 C38 52 46 76 52 98 Z"/>
        <path d="M60 96 C58 64 60 34 66 8 C70 36 68 66 66 98 Z"/>
        <path d="M62 98 C70 72 86 50 108 38 C88 58 76 80 70 100 Z"/>
        <path d="M58 100 C46 88 28 82 8 82 C28 90 42 96 54 104 Z"/>
        <path d="M64 100 C78 90 96 88 114 92 C94 96 80 100 68 106 Z"/>
      </g>
      <path class="plant__pot" d="M34 100 L86 100 L80 146 L40 146 Z"/>
      <path class="plant__rim" d="M30 96 L90 96 L90 106 L30 106 Z"/>
    </svg>

    <div class="sand" aria-hidden="true"></div>

    <!-- the curtain: one canvas over the whole front, so a strand can swing past the frame -->
    <canvas class="curtain" data-curtain aria-hidden="true"></canvas>

    <!-- the doorway is a button: a click (or Enter) walks through the curtain -->
    <button class="walk" type="button" aria-label="Walk in through the bead curtain" data-walk></button>

    <p class="hint" data-hint>Brush the curtain with the pointer. Click to walk in.</p>
  </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.

31 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 bead curtain” from Animorio and fit it into my site

What it does

The front of a little beach kiosk, with the door open and the name of the place inside, in the dark. A curtain of bead strands hangs in front of the door: turned wooden beads, glass beads and shells at the end of every strand, and together they draw a sun setting over the sea. On arrival the strands drop from the rod and stretch out bouncing, then a first guest walks in. Brushing them with the pointer the strands move aside like chained pendulums, knock into their neighbours, swing and slowly stop, and the drawing of the sun bends with them. The beads spin as they swing and the glass sends little glints. A click walks through the curtain: the strands part sideways in the middle, the title inside hops letter by letter, and then the curtain closes again, swinging.

How it works

Every strand is a chain of points

Every bead is a point with its current and its previous position (Verlet): the difference is its speed, which loses a little at every step, plus gravity. The first point is nailed to the rod. The physics runs at 120 steps a second, at a fixed step, whatever the screen.

The string pulls, the beads touch

Between two beads the string only pulls when it is taut, like a real cord; if they get too close the beads push each other away. Beads knock into those of the next strand, and a simple rule keeps the strands in order from left to right, so they never cross or tangle.

The pointer pushes

The pointer is a circle: the beads inside are pushed out and take along a little of its movement, measured along the path travelled in the frame, so a fast sweep does not skip strands. Moving a position in Verlet means giving it speed: the strand sets off by itself.

The drawing and the light

The colour of every bead is chosen once, looking at where it sits at rest in the doorway: inside the circle of the sun, on the rays, in the sea. When the strands move the drawing bends by itself. Every kind of bead is drawn beforehand in 16 turned views; when the bead rolls the next view is taken, and the glass lights a four-pointed glint when it moves fast.

Walking through

On a click a GSAP timeline opens a gap in the middle, as wide as a person and narrower at the top: the beads inside the gap are moved to its edge. The gap closes slowly and the strands go back to their place swinging; meanwhile the letters of the title hop with an elastic and the light inside warms up.

Values to change

NameFileDefaultWhat it changes
STRANDSscript.js24How many strands hang in the doorway (six tenths on a phone).
BEADSscript.js22How many beads on every strand: more beads, smaller beads.
SWINGscript.js1How hard the pointer pushes the strands.
DAMPINGscript.js1How fast the strands calm down: 0.3 lets them swing for a long time.
BREEZEscript.js1The breeze that gently rocks the curtain on its own (0 = none).
OPENscript.js1How wide the curtain opens when you walk through.
FIGUREscript.js'sun'The picture of the beads: 'sun' (a sunset over the sea), 'wave' (a wave) or 'plain' (just wood and shells).
--sunstyle.css#f5b433The colour of the sun’s beads (the rays are --ray, the sea --sea and --deep, the wood --wood and --wood-dark, the shells --shell).

Try them in the Playground

When to use it

For the entrance of a summer site: a beach bar, a lido, a festival, a shop of handmade things. The curtain is the door: you play before going in.

On phones

There are fewer, bigger strands, and they move as you drag a finger across the curtain; a tap walks through it. The doorway is narrower and the surfboard and the plant disappear, but the physics is the same.

With reduced motion

The curtain stays still, already hung. The beads near the pointer fade a little to let you see inside, and a click only fades the whole curtain for a moment.

Pitfalls

  • If two strands only collide bead against bead, a hard push makes them pass through each other and they stay tangled: one more rule keeps every bead to the right of the same bead on the strand before.
  • With the beads all heaped in the same point the “don’t overlap” rule makes them explode in random directions: for the opening drop they start already in a row, touching, and strands don’t knock their neighbours until they have stretched out.
  • A big move in one step becomes a huge speed and throws the strands out of the doorway: the speed has a cap and the door jambs stop the strands.
  • Drawing every bead with its gradients on every frame costs too much: every kind is drawn once in 16 views on small canvases, then copied rotated with drawImage.
  • Physics tied to the frame runs fast on a 120 Hz screen and slow at 60: time is accumulated and fixed steps of 1/120 of a second are taken, eight per frame at most.

Libraries

GSAP 3.15.0, Fraunces (font variabile) 5.3.0, Mona Sans (font variabile) 5.3.0.

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

Testing

Tested on 10 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 animations