
The swatch fan menu
Menus, Physics, Transitions, Hover
NewFree
The card of a green tea in the shop of a small tea house: over a glass cup of hot water hangs a silk pyramid of tea. With Steep, or a click or a tap on the cup, the bag goes down into the water swinging on its string and the tea comes out of it in plumes that sink and curl, because it is heavier than water, while the water slowly turns gold-green and steam rises from the rim. The fluid is real, solved on a grid (Stam's stable fluids). Lifted, the bag drips; the colour stays.
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 steeping tea</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/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the card of a green tea in the shop of a small tea house. Over a glass cup of hot water hangs a silk pyramid
of tea on its string: with Steep, or a click or a tap on the cup, it goes down into the water swinging on the string, and the
tea leaves it in plumes that curl and sink, while the water slowly turns gold-green. Lifted, it drips; the
colour stays. The cup, the water and the tea are drawn by the script -->
<article class="tea" aria-labelledby="tea-name" data-tea data-autoclic>
<div class="tea__shot" data-shot>
<canvas class="tea__canvas" role="img" aria-label="A glass cup of hot water, with a silk pyramid of tea hanging over it on its string" data-canvas></canvas>
</div>
<div class="tea__body">
<p class="tea__kind">Green tea · Shizuoka</p>
<div class="tea__head">
<h2 class="tea__name" id="tea-name">Sencha Asamushi</h2>
<p class="tea__price">€14</p>
</div>
<div class="tea__meta">
<p class="tea__notes">Grassy · Marine · Sweet</p>
<p class="tea__weight">50 g</p>
</div>
<div class="brew">
<p class="brew__guide"><span class="brew__label">Brew</span> 70 °C · 90 s</p>
<button class="pill pill--steep" type="button" data-steep>
<span class="pill__icon" aria-hidden="true">
<svg class="steep-icon" viewBox="0 0 24 24">
<path class="steep-icon__water" d="M3.5 17.2c1.6-1 3.1-1 4.7 0s3.1 1 4.7 0 3.1-1 4.7 0 2.4.8 2.9.4"/>
<g class="steep-icon__bag" data-bag-icon>
<path d="M12 2.4v5"/>
<path d="M8.2 7.6h7.6L12 14.4z"/>
</g>
</svg>
</span>
<span class="pill__label" data-label>Steep</span>
</button>
</div>
<div class="buy">
<button class="pill pill--add" type="button" data-add>
<span class="pill__clip" aria-hidden="true">
<span class="add__fill" data-fill>
<svg class="add__wave" viewBox="0 0 96 8" preserveAspectRatio="none" data-wave><path d="M0 4c6-4 12-4 18 0s12 4 18 0 12-4 18 0 12 4 18 0 12-4 18 0 6 2 6 2V8H0z"/></svg>
</span>
</span>
<span class="pill__icon" aria-hidden="true">
<svg class="add__glyph" viewBox="0 0 24 24" data-cart><path d="M3.4 4.6h2.3l2.1 9.6a1.7 1.7 0 0 0 1.7 1.3h7.1a1.7 1.7 0 0 0 1.7-1.3l1.4-6.4H6.6"/><path d="M10.2 19.4a.9.9 0 1 0 0 .01M16.6 19.4a.9.9 0 1 0 0 .01"/></svg>
<svg class="add__glyph add__tick" viewBox="0 0 24 24" data-tick><path d="M5.6 12.6l4.1 4.1 8.7-9.2"/></svg>
</span>
<span class="pill__label" data-label>Add to cart</span>
</button>
<button class="pill pill--undo" type="button" data-undo hidden><span class="pill__label">Undo</span></button>
</div>
<p class="sr" aria-live="polite" data-live></p>
</div>
</article>
</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.
38 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 steeping tea” from Animorio and fit it into my siteEverything is drawn on a board of 324 by 300 points, scaled to the canvas. The wall, the table and the shadows are one layer; the cup is three more, made again only when the size changes: the back (the glass seen through, the far rim), the water's surface (the window mirrored, the dark and bright meniscus) and the front (the dark edges, the window's strips of light, the rim, the thick base, the handle). The water is a lens: every column of pixels behind it is taken from another column of the background, wider in the middle and narrow at the sides, and shifted up and down, so the edge of the table bends.
The velocity lives on a grid of cells CELL pixels wide, cut to the shape of the water: the glass is a wall the pressure does not cross. Every step the tea pushes the water down as strongly as it is concentrated (SINK), the eddies are kept alive by a push round every swirl (vorticity confinement, CURL) only where there is tea, the bag drags the water along and a little viscosity draws every cell towards the mean of its neighbours; then the velocity carries itself back along the flow (semi-Lagrangian) and a pressure, found with over-relaxed Gauss-Seidel starting from the last one, takes the divergence out so the water never squeezes (Stam's stable fluids).
The tea lives on a grid twice as fine and goes with the flow forwards and back again (MacCormack, held between its four neighbours), so its threads stay fine. The bag gives it from its lower faces, with a noise that changes seven times a second and lets it out in several threads: a lot as it goes in and whenever it moves, then less and less. Slowly the tea dissolves into an even colour of the whole cup, a little stronger at the bottom. It is drawn as light taken away (Beer-Lambert): the colour of the tea at full strength in :root says how much it takes of each channel, a table of 1024 entries turns any depth of tea into the colour that passes, and the picture multiplies the water.
The top of the bag is a Verlet point hanging from a string that pulls but never pushes: when the water holds the bag up the string goes slack and bends. Its weight and drag move from those of the air to those of the water by how deep it is, in steps of 1/240 of a second; the bag's angle follows the string on a damped spring. The hand is a GSAP timeline, started only by Steep or a click on the cup: it lowers the bag drifting a little to the side, dunks it twice and lets it be. In the water the bag looks wider, as seen through the curved glass, and drags the fluid.
Out of the water, a drop swells at the tip of the bag and falls, more often the fuller the bag is. Every drop that lands makes a ring on the surface (a bright and a dark ellipse that spread) and a little cloud of tea pushed down, which becomes a plume. The steam is three threads of points rising and swaying on two sines, drawn in strokes that widen and fade; it thins out over a minute, as the water cools.
The tea steeps only when asked: Steep (Enter or Space too), a click or a tap on the picture; Lift or another click takes it out. The pointer over the picture only gives a foretaste: a GSAP tween lowers the hand 9 pixels with a bounce and gives the bag a small push, so it comes down into the mouth of the cup and sways, always above the water; leaving the picture it goes back up, and on the rest of the card nothing happens. Add to cart fills like a cup (a film with a wave on top that rises), then Added with its tick, Undo, and back to rest; an aria-live status says every step. The time step is limited to 1/30 of a second; the pendulum sleeps under half a pixel a second, the fluid once the bag gives nothing more and the tea has mixed in, the steam after a minute: then nothing is drawn any more.
| Name | File | Default | What it changes |
|---|---|---|---|
STEEP | script.js | 1.3 | The seconds the hand takes to lower the tea bag into the water. |
LIFT | script.js | 1.1 | The seconds it takes to lift it out again. |
SWING | script.js | 0.4 | How freely the bag swings on its string in the air: the share of its speed it keeps each second (0.05 to 0.9). |
SINK | script.js | 64 | How hard the tea falls through the water: how much heavier than the water it is, in pixels a second squared. |
CURL | script.js | 4 | How much the falling tea curls over into eddies (0 = smooth streams). |
STRENGTH | script.js | 1 | How much tea the leaves give: more is a darker cup. |
STEAM | script.js | 0.8 | How much steam rises from the cup, from 0 to 1. |
CELL | script.js | 2.6 | The size of a cell of the water's simulation, in pixels: smaller is finer and slower. |
WORDS | script.js | ['Lift', 'Adding', 'Added'] | The steep button with the bag in the water, then Add to cart while it works and once done. |
For the card of a tea, an infusion or a coffee in an online shop; wherever a product is best understood seen at work (a dye, an ink, a bath salt, a syrup), and for a product page that wants a moment to watch before the cart.
The card is 340 pixels wide, or the screen minus 32, and the scene is drawn again at the real size. A tap on the picture puts the bag in to steep and another takes it out, like Steep and Lift; the mouse's foretaste is not there on a phone, since the tap does it all; the buttons are 50 and 42 pixels high. Under 360 pixels the name and the pills tighten a little. The simulation is the same as on a computer: the grid is small (about 45 by 55 cells, and twice that for the tea) and costs a couple of milliseconds a frame.
With the pointer over the picture the bag stays still. Steeped, it does not go down or swing: it appears in the water in a fade and leaves the same way. No plumes, drops, rings or steam: the water takes its colour in a slow fade and keeps it. The buttons' words change in a fade and the pills do not swell.
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 22 KB; the libraries: GSAP 28 KB.
Tested on 7 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.