
The slide-to-confirm button
Buttons, Physics, Transitions
NewFree
Clearing a cache made as a windscreen in the rain at night: every drop is a small lens that shows the city lights behind the glass upside down and sharp, while the wet glass around it shows them blurred. The big drops slide down in fits and starts, leave a trail of droplets and swallow the ones they meet. Pressed, the two wipers start: every pass clears its arc and pushes the water away, the rubber blade flips over at every reversal, and less and less rain comes back: the clear glass is the progress. At the end the glass dries and a glint runs across it: 2.4 GB cleared.
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 windscreen wiper cleanup</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the windscreen wiper cleanup: clearing a cache shown as a rainy windscreen at night. Raindrops cover the glass
and each one shows the city lights behind it upside down; the big ones slide, leave a trail and swallow the
small ones. Pressed, the two wipers start: every pass pushes the water away, and less and less rain comes
back, so the clear glass is the progress. At the end the glass is dry and a glint runs across it. The glass,
the lights, the drops and the wipers are painted by script.js on the canvas -->
<section class="wipe" aria-label="Clear cache" data-wipe>
<div class="wipe__glass" role="progressbar" aria-label="Cache clearing progress" aria-valuemin="0" aria-valuemax="100"
aria-valuenow="0" aria-valuetext="Ready to clear 2.4 GB" data-scene>
<canvas class="wipe__paint" aria-hidden="true" data-paint></canvas>
</div>
<div class="wipe__info" aria-hidden="true">
<p class="wipe__title">
<svg class="wipe__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="wipe__swap" data-title>System cache · 2.4 GB</span>
</p>
<p class="wipe__pct" data-pct>0%</p>
<p class="wipe__meta"><span class="wipe__swap" data-meta>Browsers, thumbnails and logs</span></p>
</div>
<div class="wipe__buttons">
<button class="pill" type="button" data-go data-autoclic><span class="pill__label" data-label>Clear cache</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.
47 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 windscreen wiper cleanup” from Animorio and fit it into my siteThe street behind the glass is drawn once, twice: sharp, with the lights as out of focus discs with a brighter rim, and blurred, with the same lights twice as wide and paler and a milky veil over them. Both are 40 units wider than the glass on every side, for the drops near the edge. A third canvas, at half resolution, is the mask of how clear the glass is: every frame paints the blurred city and over it the sharp one cut out by the mask (copy and then source-in on a canvas in between). The wipers and the sliding drops paint the mask, the rain mists it by taking a little off everywhere every frame (destination-out with an alpha of 1 − e^(−6·rain·dt)).
A drop is drawn as an elliptical clip holding the sharp city around it, taken from a square 3.2 times its radius wide, flipped both ways (scale(−1, −1)) and made smaller: what a drop on a glass really does. Over it a single picture is stretched, made once: the dark rim where the drop reflects the dark, a light crescent at the bottom (a radial gradient with its centre moved up, which crosses the circle only at the bottom) and the highlight at the top left. The droplets too small to show the city are a speck of light with a faintly dark rim, stamped once and for good into a fourth canvas, which evaporates slowly so it never fills up.
Every drop has a threshold of its own, around 3.4 units: above it gravity pulls with a force in proportion to how far it is above, a friction holds it back, and now and then the glass snags it and lets it go again. As it slides it stretches with its speed, takes the droplets out of the mist (and grows a little), clears a strip in the mask and now and then leaves a droplet behind, losing its water. Two drops that touch become one, with the area of both and the centre moved toward the bigger one: the drops are sorted by x and only near ones are compared.
The two arms are parallel and follow the same angle: half a cosine for the stroke, a pause at the reversal, half a cosine to come back. Every frame the slice of ring between the angle before and the angle now clears the mask and wipes out the mist. The drops inside the slice hook onto the blade: they keep their distance from the hub and sit just ahead of the rubber, where they join into a row of beads (never bigger than 4 units: the rest runs off the edge) that loses water every frame; when the arm turns back it leaves them, and they slide away. The rubber is a spring on the angle: it leans against the speed and at the reversal flips over with a small bounce.
The demo's rain is (1 − progress)^1.25: it decides how many drops arrive every second (up to 180, plus six droplets per drop, with a ceiling of 300 drops) and how fast the glass mists over, so every pass finds less water than the one before. At the end the wipers finish their stroke and stop; the glass dries in 0.9 seconds (the drops left in the corners slide fast and fade, the sharp city covers everything) and a glint, a slanted linear gradient in lighter mode, runs across it. Stop lets the stroke finish and brings the rain back; Clear again brings a shower seven times as thick before starting over.
The glass is a role=progressbar with aria-valuenow and aria-valuetext updated at most every half second, aria-busy while it works and an aria-live line for the start, a stop and the end; the button stays the same element in every state. Clicks from a script (the library preview's) never stop and start again only after 2.6 seconds of result. The drawing loop runs only while it rains or something moves, and stops when the glass is off screen.
| Name | File | Default | What it changes |
|---|---|---|---|
SECONDS | script.js | 9 | How long the demo's cleanup takes, in seconds (a real one follows the files as they are deleted). |
ITEMS | script.js | [['Browser caches', 0.92], ['Thumbnails', 0.41], …] | What gets cleared, each with its name and its gigabytes; the total is also in the words at rest in index.html. |
STROKE | script.js | 0.62 | The seconds of one pass of the wipers, from one side to the other. |
PAUSE | script.js | 0.09 | The small hesitation at the reversal, in seconds. |
SWEEP | script.js | 160 | The arc of a pass, in degrees: under 150 leaves the top right corner wet. |
RAIN | script.js | 180 | The drops that land on the glass every second in full rain (plus six times as many droplets); at rest a little over a tenth of them. |
LENS | script.js | 3.2 | How much of the world behind fits in a drop: higher, the flipped picture is smaller and holds more lights. |
SLIDE | script.js | 3.4 | The radius past which a drop starts to slide, in drawing units (the glass is 380 wide). |
GRAVITY | script.js | 150 | How hard the big drops are pulled down, in units per second squared. |
WORDS | script.js | { busy: 'Clearing cache', done: 'cleared', stopped: 'Clearing stopped' } | The words under the glass while it clears, at the end (after the gigabytes) and after Stop; the one at rest is changed in index.html. |
LABELS | script.js | { busy: 'Stop', done: 'Clear again' } | The button's words while it clears and at the end; the one at rest, Clear cache, is changed in index.html. |
For a wait of a few seconds that takes something away: emptying a cache or the bin, freeing space, deleting temporary files, clearing a history, the maintenance screen of a car or driving app. The easing rain says how far along things are without reading anything, and the clear glass at the end is the reward. For a wait under two seconds it is too much (not even one pass shows), and it does not belong on a light page: it is made for a dark interface.
The component is 380 pixels wide and on a phone takes the width of the screen less 16 pixels a side (358 at 390): the drawing scales with the width and the canvas paints at the screen's real density, up to twice, so the drops stay sharp. There are at most 300 big drops, the heaviest work (the two cities) is done once and the drawing stops when the glass leaves the screen. The pill is 44 tall: under a finger it squashes and springs back; the wipers' flick is there with the mouse and the keyboard.
No falling rain, sliding drops, moving wipers or glint at the end: the glass stays wet and still, and with the progress the drops and the mist fade away as the sharp city appears, along with the percentage. At the end the glass is clear; the words change with a fade and the tick appears without drawing itself.
GSAP 3.15.0, Archivo (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 15 KB; the libraries: GSAP 28 KB.
Tested on 8 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.