Skip to content
animorio
IT
All components

The jelly button

Buttons, Physics, Hover, TextGSAP, CanvasAdvancedCompressed weight: Demo 13 KBGSAP 28 KBFreeDownload the zip

A big Get started button made of translucent strawberry jelly, a real soft body with forty eight points round its edge, shape springs and a pressure that keeps its volume. The pointer coming from outside dents the surface until it slips inside, and the jelly trembles; pressed, it squashes under the finger and bounces back with a wobble that dies away; pulled and let go, it vibrates. The words are inside the jelly and bend with it, letter by letter.

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 jelly button</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fredoka@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the jelly button: a soft body of strawberry jelly drawn on a canvas, under a real transparent button. The
         pointer dents its surface, a press squashes it under the finger, a pull stretches it, and it wobbles back.
         The words are inside the jelly and bend with it -->
    <div class="jelly" data-jelly>
      <div class="jelly__pot" data-pot>
        <canvas class="jelly__canvas" data-canvas aria-hidden="true"></canvas>
        <button class="jelly__btn" type="button" data-btn data-autoclic><span class="sr" data-name>Get started</span></button>
      </div>
      <p class="jelly__hint" data-rise><span data-hint>Free for 14 days · no card needed</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.

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

What it does

On a white background a block of strawberry pink jelly shaped like a pill, glossy, with a band of light along its top edge, a white reflection at the top left, a lighter rim where the jelly is thin and, on the table, a pinkish shadow with a patch of light in front of it, the light the jelly lets through. Inside it says Get started with an arrow, in white; below, in grey, Free for 14 days · no card needed. As it comes in, the jelly drops onto the table from just above, squashes and wobbles to a stop. Bringing the pointer in from above or the sides, the surface dents round its tip as if pushed with a finger, and the sides bulge to keep the volume; pushed deeper, the pointer slips inside, the dent springs back out and the jelly trembles. Inside, moving the pointer drags the jelly a little, and it wobbles when it stops; under the tip a dimple of shade and light appears, and the arrow leans out. Pressed, the jelly squashes and spreads, deeper under the finger, and the words squash with it; let go, it bounces up past its shape and wobbles. Held and pulled, it stretches after the hand and, let go, vibrates. The click starts the sign up: the words rise and fade, Setting up comes in and the jelly gently breathes; then a little jump for joy, You’re in with a tick, and below Check your inbox to finish. After a few seconds Get started comes back. From the keyboard the focus ring follows the edge of the jelly, even while it moves.

How it works

A Verlet soft body

The edge of the jelly is made of 48 points, evenly spaced round the outline of a rectangle with round ends. Each point remembers where it was and where it is: its new place comes from the last two, the forces and a damping (Verlet integration), in six steps per frame with the step capped at 1/30 of a second. When the points' energy falls below a threshold and nothing touches them, the loop stops drawing.

Shape, edge, volume

Each point is pulled towards the place the shape at rest would give it round the body's current centre (shape matching), and the centre is pulled towards the table, a little lower so the jelly leans its weight on it. Between neighbours there are length springs and a bending spring, which keeps each point where its two neighbours put it at rest: so the edge bends in soft waves instead of crumpling. A pressure along the normals keeps the area, and a dent on one side bulges the other.

The denting finger

The pointer is a fingertip POKE pixels wide. From outside it pushes the surface inwards: each point it covers slides along its normal at rest to the far side of the tip, and loses the speed that would bring it back against it, so the dent wraps round the tip and follows it. When the tip is more than POP pixels inside the shape, it slips in and the dent springs back out at once. Inside, the pointer's speed drags the nearby points.

Pressing and pulling

A press squashes the shape the springs aim for (lower by SQUASH, wider by almost half as much) and sinks the top edge under the finger with a gaussian. Let go, the shape comes back at once and the springs throw it past: the bounce and the wobble come from the physics, not from a curve. Pulled, the points near the grip follow the hand up to PULL pixels, with a hyperbolic tangent that brakes the stretch.

The letters inside the jelly

Each letter has its centre at rest; its mean value coordinates against the 48 edge points carry it into the jelly as it is now. Two neighbouring points, four pixels to the right and below, give the local stretch, shear and turn: that is the matrix the canvas draws the letter with. So the words squash, bend and wobble with the jelly, and stay sharp text.

The light

The body is filled with a gradient from light pink at the top to deep red at the bottom, with light gathered low in the middle; the edge has a light rim inside, where the jelly is thin, and a fine dark line. The glossy band and the reflection follow the edge points moved inwards along the normals, and the shadow on the table widens and fades when the jelly jumps.

Values to change

NameFileDefaultWhat it changes
STIFFscript.js380How hard the jelly pulls back into its shape: higher wobbles faster.
DAMPscript.js3.4How quickly the wobble dies away: the share of its speed it loses each second.
SQUASHscript.js0.2How much a press squashes the jelly, as a share of its height.
POKEscript.js18The size of the fingertip, in pixels: how wide a dent the pointer pushes.
POPscript.js22How deep the pointer pushes the surface in, in pixels, before it slips inside.
PULLscript.js60How far a held jelly stretches after the hand, in pixels.
WAITscript.js1.8The seconds the pretend sign up takes.
DONEscript.js2.8The seconds the button says You’re in before it is ready again.

Try them in the Playground

When to use it

For the main call to action of a playful product: an app for children or for food, a game, a creative tool, the launch page of a startup that wants to look friendly. It works on its own on a light background, with plenty of room round it so the jelly can jump; the colour changes in the CSS variables (the comments have mint too).

On phones

The jelly narrows to the width of the screen (at 390 pixels it stays 300 wide) and the canvas does not spill over. The finger has no hover: a touch presses the jelly where it lands, squashes it under the fingertip and makes it bounce when it lifts; dragging stretches it, and the button keeps touch-action: none so the finger pulls the jelly instead of scrolling the page.

With reduced motion

The jelly does not move: no drop, no dents, no bounces or jumps. Pressed it darkens slightly, the words and the line below change with a fade, without rising. The drawing is redone only when something changes.

Pitfalls

  • With the points held only by the shape and the length springs, on impact the edge crumpled into many small waves: a bending spring between each point and its two neighbours keeps it soft.
  • Pushing the points out of the pointer's tip while keeping their speed made it grow at every step against the tip, and the jelly exploded: the part of the speed against the tip must be removed.
  • Pushed away from the centre of the tip, the points above a pointer already inside the jelly were pushed outwards, making a bump instead of a dent: the push goes along the normal at rest, always inwards.
  • Without a limit, the tip also pushed the opposite edge of the jelly, whose normal is the same turned round: only the surface within POP plus the tip in front of the finger counts.
  • The strips of a picture of the words, drawn one by one with drawImage, brought the canvas to its knees without a graphics card: each letter drawn with its own matrix costs a dozen calls.
  • Two labels fading at the same time overlapped while the jelly was squashed: now the old one is gone before the new one arrives.
  • With the jelly resting exactly on the table, pressing the middle lifted its ends like a banana: the centre is pulled a little below the table, so the jelly weighs on it.

Libraries

GSAP 3.15.0, Fredoka (font variabile) 5.3.0.

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

Testing

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