
The water button
Buttons, SVG, Physics, Hover
NewFree
The night reading switch, in the minimal style: the track is a small window with a sky and a low sun, and the knob is the pull cord of a roller blind. Switched on, the blind unrolls with its fine folds and covers the window while night falls behind it; switched off, a tug and the spring rolls it up in a snap, bouncing twice against the roller.
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 roller blind switch</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<div class="setting" data-setting>
<div class="setting__text">
<label class="setting__name" id="night-name" for="night-switch">Night reading</label>
<span class="setting__sub" aria-hidden="true">
<span class="setting__subwords">
<span class="setting__s" data-sub-off>Blind up, full light</span>
<span class="setting__s" data-sub-on>Blind down, easy on the eyes</span>
</span>
</span>
</div>
<div class="setting__ctrl">
<span class="setting__word" id="night-word" aria-hidden="true">
<span class="setting__w" data-word-off>Off</span>
<span class="setting__w" data-word-on>On</span>
</span>
<button class="switch" id="night-switch" type="button" role="switch" aria-checked="false" aria-labelledby="night-name night-word" data-switch data-autoclic>
<svg class="switch__art" viewBox="0 0 104 56" aria-hidden="true" focusable="false">
<defs>
<clipPath id="window">
<rect x="2.5" y="2.5" width="99" height="51" rx="25.5"></rect>
</clipPath>
<linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" data-sky-top stop-color="#dfe9ef"></stop>
<stop offset="1" data-sky-bottom stop-color="#fbf6ec"></stop>
</linearGradient>
<linearGradient id="fall" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#000" stop-opacity="0.16"></stop>
<stop offset="1" stop-color="#000" stop-opacity="0"></stop>
</linearGradient>
</defs>
<g clip-path="url(#window)">
<rect class="switch__sky" x="0" y="0" width="104" height="56" fill="url(#sky)"></rect>
<circle class="switch__sun" data-sun cx="32" cy="48" r="10"></circle>
<path class="switch__moon" data-moon d="M0 -5.2 A5.2 5.2 0 1 0 4.6 2.4 A4.1 4.1 0 1 1 0 -5.2 Z"></path>
<rect class="switch__fall" data-fall x="0" y="0" width="104" height="5" fill="url(#fall)"></rect>
<rect class="switch__cloth" data-cloth x="0" y="0" width="104" height="10"></rect>
<path class="switch__slats" data-slats d=""></path>
<rect class="switch__rail" data-rail x="0" y="0" width="104" height="1.8"></rect>
<rect class="switch__roll" data-roll x="0" y="0" width="104" height="8"></rect>
<line class="switch__rollline" data-rollline x1="0" y1="0" x2="104" y2="0"></line>
</g>
<rect class="switch__track" x="1" y="1" width="102" height="54" rx="27"></rect>
<g data-cord>
<line class="switch__cord" data-cordline x1="0" y1="0" x2="0" y2="8"></line>
<path class="switch__pull" data-pull d="M0 0 C1.9 0 3.1 1.6 3.1 3.6 C3.1 5.9 1.7 7.6 0 7.6 C-1.7 7.6 -3.1 5.9 -3.1 3.6 C-3.1 1.6 -1.9 0 0 0 Z"></path>
<path class="switch__gleam" data-gleam d="M-1.4 2.2 C-1.9 3 -2 4 -1.7 5"></path>
</g>
</svg>
</button>
</div>
</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 roller blind switch” from Animorio and fit it into my siteEverything is in one object of numbers: how far down the blind is p, the tug, the lean under the mouse, the press and the word. A render function, called by the GSAP ticker on every frame, writes the cloth, the folds, the rail, the roller, the cord and the sky from it.
The fine folds are a single path redrawn on every frame, one line every FOLD pixels counted from the rail upwards: so as the blind comes down, new folds come off the roller one at a time, like real cloth, and the roller gets thinner by as much as has unrolled.
Switched on: the tug lengthens the cord by TUG pixels, then p goes OVERSHOOT pixels past the bottom with power2.inOut in DROP seconds and comes back with sine.out. Switched off: another tug frees the catch, p goes back to zero with power3.in in SNAP seconds, which speeds up like a spring, and two ever smaller bounces against the roller.
The cord's angle is a damped spring pushed by the rail's acceleration: when the blind starts or stops, the acorn swings and settles by itself. The sky goes to night blue with gsap.utils.interpolate on the gradient's two colours, the sun sinks and the moon comes up.
It is a button with role="switch" and aria-checked, labelled by the setting's name and the word; Space and Enter turn it like a click, the right and left arrows switch it on and off, and focus shows as an orange ring. A click halfway stops the running turn and starts the new one from where the blind is.
| Name | File | Default | What it changes |
|---|---|---|---|
DROP | script.js | 0.95 | How long the blind takes to unroll, in seconds. |
SNAP | script.js | 0.36 | How long the spring takes to roll it up, in seconds. |
OVERSHOOT | script.js | 1.1 | How far the rail goes past the bottom before it settles, in pixels. |
BOUNCE | script.js | 1.6 | How high the rail bounces off the roller when it rolls up, in pixels. |
SWING | script.js | 1 | How much the cord swings when the rail moves (0 never). |
FOLD | script.js | 5.2 | The gap between the fine folds of the cloth, in pixels. |
TUG | script.js | 4 | How far the cord is pulled down on the tug, in pixels. |
For an on or off setting that darkens or dims: the night reading of a books or news app, dark mode, a rest mode, a blue light filter. It also suits the settings of a smart home, for real blinds, or a hotel's site.
The same with a tap: the switch stays 104 by 56, with the cord hanging below it when the blind is down; the setting's row narrows to the screen's width and the line under the name stays on one line.
No unrolling and no spring: the blind is already up or already down, the sky already day or night, the cord still; the words swap in a short fade and the line changes at once.
GSAP 3.15.0, Archivo (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 6.0 KB; the libraries: GSAP 28 KB.
Tested on 24 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.