
The cookie banner
Consent, Transitions, SVG, Physics
NewFree
An export made as a moka pot on the stove, cut away on the right like a technical drawing: inside you see the water in the boiler, the funnel of ground coffee and the chimney in the middle of the upper chamber. Press Export report and the blue flame catches from the igniter and runs round the ring, the water goes down and the coffee climbs the chimney, wells over and runs down into the chamber: its level is the percentage. At the end the pot sputters, throws up spurts of foam, hisses steam from the spout and from under the rattling lid, and the gas goes out: Report ready.
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, viewport-fit=cover">
<title>The moka pot loader</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the moka pot loader: an export shown as a stovetop moka pot on a small gas ring, its right side cut away like a
technical drawing so you see the water in the boiler and the chimney in the upper chamber. Pointed at, the
button makes the igniter spark; pressed, the blue gas lights, the water goes down, the coffee comes up the
chimney and runs into the chamber, and its level is the export's progress. At the end the pot sputters and
hisses, the gas goes out and the report is ready to download. The pot is drawn by script.js -->
<section class="moka" aria-label="Report export" data-moka>
<!-- four layers, bigger than the pot's place so the steam has room above it: the burner and the inside of the
pot; the flame and the liquids; the outside and the hatched cut; the steam -->
<div class="moka__scene" role="progressbar" aria-label="Report export" aria-valuemin="0" aria-valuemax="100"
aria-valuenow="0" aria-valuetext="Ready to export" data-scene>
<div class="moka__layers" data-layers>
<svg class="moka__art" viewBox="25 40 250 290" preserveAspectRatio="none" aria-hidden="true" data-art="back"></svg>
<canvas class="moka__art" aria-hidden="true" data-fluid></canvas>
<svg class="moka__art" viewBox="25 40 250 290" preserveAspectRatio="none" aria-hidden="true" data-art="front"></svg>
<canvas class="moka__art" aria-hidden="true" data-air></canvas>
</div>
</div>
<p class="moka__status" aria-hidden="true">
<svg class="moka__tick" viewBox="0 0 24 24" data-tick><path d="M5.5 12.6l4.2 4.2 8.8-9.4" pathLength="1"/></svg>
<span class="moka__swap" data-status>Ready to export</span>
<span class="moka__pct" data-pct></span>
</p>
<div class="moka__buttons">
<button class="pill" type="button" data-go data-autoclic><span class="pill__label" data-label>Export report</span></button>
<button class="pill is-quiet" type="button" hidden data-again><span class="pill__label">Brew again</span></button>
</div>
<p class="sr" role="status" aria-live="polite" data-live></p>
</section>
</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.
51 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 moka pot loader” from Animorio and fit it into my siteOf an octagon seen from the front you see three faces: the front one ends at tan 22.5° of the half width (0.414), the two slanted ones go from there to the edge. The pot’s profile gives the half width at every height (the boiler narrows going up, the upper chamber flares), and every band (lid, rim, chamber, collar, boiler, bevel) is drawn once in SVG with a gradient for each face, chosen by how the face is tilted towards the light. On the slanted face a blurred white strip is the reflection, and over it lies a pattern of thin random lines, always the same, for the brushed finish; everything is clipped to the left of the cut line.
Right of the cut the walls are polygons filled with two hatch patterns, at 45° and at −45°, because two parts that touch in a technical drawing have opposite hatching: the boiler with its base, the chamber with its floor and the chimney, the lid. The funnel’s sheet metal is a solid line, the filter and the funnel’s bottom a dashed one, the thread a zigzag. There are four layers: at the back the inside of the pot and the burner (SVG), then a canvas with the flame and the liquids, then the outside and the cut walls (SVG), and over everything a canvas with the steam. So the liquids’ edges end under the hatching, and every frame only the two canvases are painted again.
The demo’s export is a list of steps, each a jump forward or a pause: the weights change a little every time but together they last SECONDS. The coffee’s level goes from the chamber’s floor to full with the percentage, the water’s from a full boiler down to the funnel’s stem. How hard the coffee comes out of the chimney follows the speed of the progress, smoothed: 0.14 + 1.6 × speed, so the stream gurgles on the jumps and stays a trickle in the pauses. The gurgle is the sum of two sines, plus a jump now and then that swells the dome and throws two drops; the streams down the chimney widen and narrow with a wave that runs down them.
The coffee’s surface, and the water’s, is a row of 40 points under a damped wave equation: v += (c²/dx² · (h₋₁ + h₊₁ − 2h) − d·v − 5h)·dt, in steps of 5 thousandths of a second, with walls that reflect. The streams push it down where they fall, the drops where they land, bursting bubbles pull it up; in the coffee the bubbles carried down by the streams rise again and float as foam. When the biggest ripple is below 0.04 units the surface rests, and when nothing moves the loop stops drawing.
Eighteen flames sit on an ellipse round the burner’s cap: they are painted from the back to the front with the cap in between, each a drop with a pale cone inside, bent outwards and pressed flat under the pot, and they flicker with two sines. They light in order, starting from the igniter. At the end the water drops below the stem and steam blows through it in slugs; the spurts are particles with gravity that fall back into the coffee and make it slosh, the puffs of steam are a white body over a blue grey edge (on white, steam shows by its shadow) and the lid turns on its hinge with a bounce.
The pot is a role=progressbar with aria-valuenow and aria-valuetext updated at most every 0.6 seconds, aria-busy while it works and an aria-live line for the start, the end and the download. The button stays the same element in every state, so keyboard focus is never lost; Brew again hands it back to the button as it goes. Clicks from a script (detail 0, the library preview’s) never download: after 2.5 seconds of Report ready they brew again, so the thumbnail runs by itself.
| Name | File | Default | What it changes |
|---|---|---|---|
SECONDS | script.js | 3.6 | How long the demo’s export takes, in seconds, without the gas lighting up and the sputter at the end (a real one follows the server’s work). |
STEPS | script.js | [[0.2, 0.9], [0, 0.45], [0.47, 1], …] | The export in fits and starts: for each step how far it gets (from 0 to 1) and how much of the time it takes; a step that goes no further than the last one is a pause. |
JITTER | script.js | 0.25 | How much the steps’ weights change from one run to the next: 0 always the same. The length stays SECONDS. |
HEAT | script.js | 0.6 | The seconds between lighting the gas and the coffee reaching the top of the chimney. |
SPURTS | script.js | 3 | The spurts of foam in the sputter at the end, each with its puff of steam and the lid rattling. |
FLAME | script.js | 15 | The flames’ height, in drawing units (the pot is about 200 tall); taller ones are pressed flat under the pot. |
PORTS | script.js | 18 | The burner’s ports, that is how many flames there are round the ring. |
GRAVITY | script.js | 320 | The gravity on the drops and the spurts, in drawing units per second squared. |
WAVE | script.js | [90, 2.4] | The surface of the coffee and the water: how fast a ripple runs (units a second) and how quickly it dies down. |
LABELS | script.js | { busy: 'Exporting…', done: 'Download', saved: 'Downloaded' } | The button’s words while it works, at the end and once downloaded; the one at rest, Export report, is changed in index.html. |
WORDS | script.js | { busy: 'Brewing your report…', done: 'Report ready' } | The line under the pot while it works (followed by the percentage) and at the end; the one at rest, Ready to export, is changed in index.html. |
For a wait of a few seconds that ends with something to take away: exporting a report or a PDF, preparing an archive to download, generating an invoice, a backup. It suits a product with a warm, crafted or Italian tone, or where the wait can be told as «we are making it for you»; the cut-away pot says how far along things are even without reading the number. For a very short wait, or one that does not end with something in hand, it is too much.
The component is 360 pixels wide and on a phone takes the width of the screen less 16 pixels a side (358 at 390); the pot stays 240 wide and the drawing is vector, so it stays sharp at any density, and the two canvases paint at the screen’s real density, up to twice. The drawing’s layers reach above the pot for the steam without scrolling the page sideways. The buttons are pills 44 tall: under a finger they squash and spring back; the pill that swells, the words that widen and the igniter’s sparks on the way past are there only with the mouse (or the keyboard, for the sparks).
The flame fades in and out and does not flicker, no sparks, no drops, bubbles, foam, spurts or steam, the lid does not rattle and the surfaces stay flat. The coffee still climbs the chimney and fills the chamber and the water still goes down, with the percentage, because they are what says how far along things are; the stream down the chimney stays still and thin. The words change with a fade and the tick appears without drawing itself.
GSAP 3.15.0, Bricolage Grotesque (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.