
The water button
Buttons, SVG, Physics, Hover
NewFree
A pill of cotton paper with a tooth and fibres, and over it a fountain pen that follows the pointer, a drop of ink swelling on its nib. At a click the drop falls, bursts into a crown and the ink creeps out by capillarity along the fibres, with a branching front, until the whole button is soaked: there Added to bag shows, pale on the dry ink. A second click takes it out of the bag and the paper comes back clean.
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 ink bleed button</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/opsz.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/opsz-italic.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the ink bleed button: a pill of cotton paper. Over it a fountain pen follows the pointer and a drop of ink swells
on its nib; a click lets the drop fall, it bursts into a crown and the ink creeps out along the paper's fibres
until the whole button is soaked, with Added to bag pale on the dry ink. A second click bleaches it clean -->
<div class="ink" data-ink data-autoclic>
<button class="ink__btn" type="button" aria-label="Add to bag, €18" data-btn>
<!-- the paper and the printed words; the ink, drawn on a canvas; the stain, the pale words, the grain and the pen -->
<svg class="ink__layer ink__layer--back" aria-hidden="true" data-back></svg>
<canvas class="ink__layer ink__soak" aria-hidden="true" data-soak></canvas>
<svg class="ink__layer ink__layer--front" aria-hidden="true" data-front></svg>
</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>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.
18 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 ink bleed button” from Animorio and fit it into my siteThe fountain pen is a hand-drawn SVG (lacquered barrel, ring, gold nib with its slit and breather hole) that chases the pointer on a spring integrated by hand on GSAP's ticker; its lean follows the horizontal speed. The drop on the tip grows in SWELL seconds and hangs on a second spring, pushed by the pen's acceleration: it swings when the pen starts and stops. The shadow on the paper moves and widens with the pen's height.
The pill is a grid of cells, one per pixel. Each cell has a cost for the ink: a noise stretched across like the sheet's grain, raised to an exponent with BRANCH (higher, more difference between easy and hard cells, so more branches), and divided along the fibres, which are the same curves drawn in the grain. Going up and down costs more than across: the fibres lie across.
From the point where the drop falls, Dijkstra's algorithm finds for each cell how far the ink must travel along the cheapest way: the front that comes out of it branches, with fingers along the fibres and bays where the paper is hard. It is worked out a slice per frame while the drop falls, so the click does not stutter. Then the front moves over that map by Washburn's law: the distance grows with the square root of the time, fast at first and slower and slower.
Every frame the canvas is painted again from the map: ahead of the front a light halo of water, on the front a darker line where the pigment gathers, behind it wet blue that turns blue-black in DRYING seconds, a little darker where the ink pooled in a fibre. The crown on top is a path redrawn every frame (a wobbling circle, SPIKES bell-shaped spikes and droplets) with a fine turbulence filter.
At the second click another map is worked out from the point clicked, on the same paper: a pale front runs along the same fibres, and where it passes the ink pales to a light blue and fades in UNDO seconds, until the paper is clean again. Added to bag goes at once; Add to bag is printed underneath on the paper and comes back with it.
| Name | File | Default | What it changes |
|---|---|---|---|
SWELL | script.js | 0.9 | The seconds the drop takes to swell on the nib. |
SOAK | script.js | 1.8 | The seconds the ink takes to creep through the whole button. |
DRYING | script.js | 0.6 | The seconds the ink stays wet blue after the front has passed. |
FIBRES | script.js | 1 | How much the ink runs along the paper's fibres: 0 not at all, 2 in long fingers. |
BRANCH | script.js | 1 | How ragged and branched the front is: 0 a smooth blot, 2 very ragged. |
SPIKES | script.js | 13 | How many spikes the crown of the drop has. |
UNDO | script.js | 1.1 | The seconds the paper takes to come back clean at the second click. |
LABEL | script.js | Add to bag | The words on the button. |
PRICE | script.js | €18 | The price beside them. |
ADDED | script.js | Added to bag | The words on the dry ink. |
For the main button of a shop or a site where paper and ink belong: fountain pens, stationers, letterpress printers, publishers, calligraphers, writing paper. It suits an action with an outcome that stays (add to bag, subscribe, sign), because the ink marks it and the second click erases it.
The pill is 320 pixels wide, or the screen minus 48, and the paper is worked out again for the real size. With no pointer passing over it, at a touch the pen comes down where the finger touches with its drop ready, lets it fall there and leaves; the second touch pales the ink from that point.
The pen does not follow the pointer: it fades in, still, right of the words, with its drop ready. At a click there is no fall and no moving front: the dry ink with the crown and Added to bag appear together in a fade, and the second click fades them away the same way.
GSAP 3.15.0, Fraunces (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 13 KB; the libraries: GSAP 28 KB.
Tested on 4 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.