
The liquid glass button
Buttons, WebGL, Hover, Physics
NewFree
The top bar of a fashion house cut from a strip of black satin. Under the page you are on the cloth is gathered, as if pinched from below: the folds run in towards the word from both sides and the light slides along them in long bright streaks. Choosing another page the gather lets go a little, runs there on a spring and pulls the cloth together again, and a soft ripple runs out of the new gather and dies away. Under the link the pointer is on the cloth gathers slightly. The satin is drawn in WebGL.
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 satin nav</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bodoni-moda@5.3.0/opsz.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the top bar of a fashion house, Velin, cut from a strip of black satin. Under the page you are on the satin is
gathered, as if pinched from below: its folds run in towards the word and the light slides along them. Going
to another page the pinch lets go and gathers the cloth again further along, the folds travel with it and a
soft ripple runs out of the new gather. The satin is drawn in WebGL: a height map of folds, lit with the
stretched highlights of a woven fabric. The links on top are the real navigation -->
<header class="bar" data-bar>
<canvas class="bar__satin" aria-hidden="true" data-satin></canvas>
<a class="brand" href="#" aria-label="Velin, home" data-brand>
<span class="brand__word">Velin</span>
<span class="brand__mark" aria-hidden="true">V</span>
</a>
<nav class="nav" aria-label="Main">
<ul class="list">
<li><a class="link" href="#" aria-current="page" data-link>New in</a></li>
<li><a class="link" href="#" data-link data-autoclic>Women</a></li>
<li><a class="link" href="#" data-link>Men</a></li>
<li><a class="link" href="#" data-link data-autoclic>Atelier</a></li>
<li><a class="link" href="#" data-link data-autoclic>Journal</a></li>
</ul>
</nav>
</header>
</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.
20 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 satin nav” from Animorio and fit it into my siteThe satin is a single WebGL pass over the whole bar. For every pixel the shader works out how high the cloth is: a long drape made of three almost vertical waves, and the folds of the gather. The slope, taken from the differences between neighbouring pixels, gives the surface's normal, and the shadow and the light come from that.
The folds of a gather are ridges that close in towards the pinched point from both sides: the shader uses the ratio between the vertical and the horizontal distance from the point, so the ridges are close together near the word and open out further away. Their depth grows out of the point and then fades within REACH pixels, and the drape round it is pulled towards the gather, so the long folds bunch up there too. The horizontal distance is softened (a square root instead of the absolute value), or a straight seam was left in the middle.
The light comes from the top left. The highlight is in two lobes, a narrow one and a wide one, and the normal is squeezed horizontally before it is worked out, as for a fabric whose threads run along the bar: so every fold carries a long streak of light. The cloth's colour and the highlight's come from the --satin and --sheen variables.
The gather's position follows the middle of the chosen link on a spring (SPRING), in steps of 1/120 of a second; its strength on another spring, which drops towards half with the speed: running, the cloth loosens, stopping, it pulls tight. When the gather arrives a ripple starts: a ring that spreads and fades in three seconds. The pointer has a lighter gather of its own (HOVER_GATHER), with its own springs.
The shader runs only while a spring moves, a ripple is alive or the entrance is playing; then the bar stays still without working anything out. Without WebGL the bar falls back to a dark ground with a soft light under the chosen link.
| Name | File | Default | What it changes |
|---|---|---|---|
FOLDS | script.js | 13 | How many folds run into the gather. |
DEPTH | script.js | 9 | How deep the folds of the gather are, in pixels of the cloth's height. |
REACH | script.js | 120 | How far from the word the gather pulls the cloth, in pixels. |
SHEEN | script.js | 0.9 | How bright the light on the folds is (0, matt cloth). |
SPRING | script.js | [120, 15] | The spring the gather runs on: how stiff, and how much it is held back (less, further it overshoots). |
RIPPLE | script.js | 1 | How strong the ripple that runs out of a new gather is (0, none). |
HOVER_GATHER | script.js | 0.5 | How much the cloth gathers under the link the pointer is on (0 to 1). |
For the header of anyone who sells or makes things of cloth and luxury: a fashion house, an atelier, a tailor, a lingerie or tie shop, a perfume brand, an elegant hotel. It suits four to six short links on a dark ground; the satin can be any colour, by changing --satin and --sheen (an ivory with warm highlights, a midnight blue, a bottle green).
Below 600 pixels the name becomes the V alone and the five links spread across the whole bar, at 14 pixels: at 390 the bar is 358 wide and 60 tall, and they all fit without spilling over. The satin is the same, with the gather and the ripple; with a finger down on a link the cloth gathers under it as with the mouse, and the tap chooses it.
The cloth does not run or ripple: choosing another link the gather is already under it and the satin is redrawn in a short fade; the pointer lights the link without gathering. When the page opens the bar fades in with the gather already in place.
GSAP 3.15.0, Bodoni Moda (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.2 KB; the libraries: GSAP 28 KB.
Tested on 19 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.