
The water button
Buttons, SVG, Physics, Hover
NewFree
The sidebar of a print studio's dashboard, made of five sheets of paper laid one on the other, from the palest on top to a full vermilion at the bottom. Round the page you are on the four top sheets are die-cut, each hole a little smaller than the one above, so the page sits at the bottom of a stepped well with a shadow under every edge. Choosing another, each sheet's hole slides there on a spring of its own: the top one first, then the deeper ones, so the new well opens sheet after sheet while the old one closes from the top. With the pointer on a page the top sheet opens a shallow tray under it.
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 layered paper sidebar</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 sidebar of a print studio's dashboard, made of five sheets of paper laid one on the other, from the palest
on top to a deep vermilion at the bottom. Round the page you are on, a hole is cut through the four top sheets,
each one a little smaller than the one above, so the page sits at the bottom of a stepped well. Choosing
another page, every sheet's hole slides there on a spring of its own, the top one first and the deeper ones
after: the new well is punched through sheet after sheet while the old one closes from the top. The sheets
are rectangles cut by masks, redrawn every frame; the links on top are the real navigation -->
<nav class="side" aria-label="Studio" data-side>
<svg class="paper" aria-hidden="true" data-paper>
<defs>
<filter id="paper-cast" x="-5%" y="-5%" width="110%" height="110%">
<feDropShadow dx="0" dy="1.8" stdDeviation="1.7" flood-color="#4a1a0a" flood-opacity="0.42"/>
</filter>
<mask id="paper-hole-3" maskUnits="userSpaceOnUse"><rect class="paper__full" data-full/><rect class="paper__cut" data-cut/></mask>
<mask id="paper-hole-2" maskUnits="userSpaceOnUse"><rect class="paper__full" data-full/><rect class="paper__cut" data-cut/></mask>
<mask id="paper-hole-1" maskUnits="userSpaceOnUse"><rect class="paper__full" data-full/><rect class="paper__cut" data-cut/></mask>
<mask id="paper-hole-0" maskUnits="userSpaceOnUse"><rect class="paper__full" data-full/><rect class="paper__cut" data-cut/><g data-shallow></g></mask>
</defs>
<rect class="paper__base" data-full/>
<g filter="url(#paper-cast)"><rect class="paper__sheet paper__sheet--3" mask="url(#paper-hole-3)" data-full data-sheet/></g>
<g filter="url(#paper-cast)"><rect class="paper__sheet paper__sheet--2" mask="url(#paper-hole-2)" data-full data-sheet/></g>
<g filter="url(#paper-cast)"><rect class="paper__sheet paper__sheet--1" mask="url(#paper-hole-1)" data-full data-sheet/></g>
<g filter="url(#paper-cast)"><rect class="paper__sheet paper__sheet--0" mask="url(#paper-hole-0)" data-full data-sheet/></g>
</svg>
<p class="group" id="group-studio">Studio</p>
<ul class="list" aria-labelledby="group-studio">
<li><a class="item" href="#" aria-current="page" data-item>
<svg class="item__icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M3.5 6.5 10 3.2l6.5 3.3v7L10 16.8l-6.5-3.3zM3.5 6.5 10 9.8l6.5-3.3M10 9.8v7"/></svg>
<span class="item__name">Orders</span>
</a></li>
<li><a class="item" href="#" data-item data-autoclic>
<svg class="item__icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M5 2.8h7l3 3v11.4H5zM12 2.8v3h3M7.6 11.2l1.7 1.7 3.3-3.6"/></svg>
<span class="item__name">Proofs</span>
<span class="item__count">3</span>
</a></li>
<li><a class="item" href="#" data-item>
<svg class="item__icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M3.2 12.6 10 16l6.8-3.4M3.2 9.6 10 13l6.8-3.4M10 3.4l6.8 3.3L10 10 3.2 6.7z"/></svg>
<span class="item__name">Paper stock</span>
</a></li>
<li><a class="item" href="#" data-item data-autoclic>
<svg class="item__icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M7.6 9.4a2.9 2.9 0 1 0 0-5.8a2.9 2.9 0 0 0 0 5.8zM2.6 16.4c.6-2.9 2.5-4.4 5-4.4s4.4 1.5 5 4.4M13.2 3.9a2.7 2.7 0 0 1 0 5.2M14.6 12.3c1.6.5 2.5 1.8 2.8 4.1"/></svg>
<span class="item__name">Clients</span>
</a></li>
</ul>
<p class="group" id="group-office">Office</p>
<ul class="list" aria-labelledby="group-office">
<li><a class="item" href="#" data-item data-autoclic>
<svg class="item__icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M5 2.8h10v14.4l-2-1.3-1.7 1.3-1.3-1.3-1.3 1.3L7 15.9l-2 1.3zM7.6 7h4.8M7.6 10h4.8M7.6 13h2.6"/></svg>
<span class="item__name">Invoices</span>
</a></li>
<li><a class="item" href="#" data-item>
<svg class="item__icon" viewBox="0 0 20 20" aria-hidden="true"><path d="M3.5 6h13M3.5 14h13M7.5 3.9v4.2M12.5 11.9v4.2"/></svg>
<span class="item__name">Settings</span>
</a></li>
</ul>
</nav>
</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.
26 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 layered paper sidebar” from Animorio and fit it into my siteInside an SVG behind the links there is a vermilion rectangle, the bottom sheet, and over it four rectangles as big as the sidebar, from coral to cream. Each has a mask: a white rectangle that keeps the paper and a black round-cornered rectangle that cuts it. With a mask two holes that overlap (the well passing over the pointer's tray) stay one hole: with a path and the evenodd rule the shared part closed up again.
Every sheet sits in a group with a feDropShadow downwards. A group's filter works on the sheet already cut by its mask, so the shadow comes from the edge of the hole and falls on the sheet below, only inside the well: that is what makes the steps read as depth.
Where the cut is going is told by two GSAP tweens, one for the top edge and one for the bottom, with a power3.inOut TRAVEL long; the front edge sets off at once and the back one after LEAD of the trip, so the hole stretches and then closes up. Every sheet's hole follows the cut on a spring of its own (SPRING), softer the deeper the sheet (LAG), drawn in by STEP pixels a step. The deep sheets arrive later: the new well is dug and the old one closes from the top by themselves.
Every link has a second hole in the mask of the top sheet only, zero tall at rest. With the pointer, a finger down or the keyboard's focus a spring opens it from its middle line to the link's size: the peach sheet shows below, with its shadow, without digging the well.
The chosen link's name turns pale (the is-deep class) only when the deepest sheet's hole is under it, at least half the link tall and centred: on the way it stays dark and reads on every sheet. The links are real links with aria-current="page"; the arrows, Home and End move the focus.
| Name | File | Default | What it changes |
|---|---|---|---|
START | script.js | 0 | The page chosen when the sidebar opens (0 is the first one). |
STEP | script.js | 4.2 | How much smaller each sheet's hole is than the one above, in pixels: the steps of the well. |
TRAVEL | script.js | 0.42 | The seconds the top sheet's cut takes to go one page down (a little more for a far one). |
SPRING | script.js | [260, 22] | The top sheet's spring behind the cut: how stiff, and how much it is held back (less, further it overshoots). |
LAG | script.js | 0.42 | How much later each deeper sheet follows the one above (0, all together). |
LEAD | script.js | 0.22 | How far ahead the front edge of a hole sets off, as a share of the trip: on the way the hole stretches. |
SHALLOW | script.js | true | The pointer opens a shallow tray in the top sheet only. |
For the sidebar of a dashboard or an app with five, six or eight pages: a print studio, a graphic design studio, a stationer's, anyone who works with paper and wants a warm, handmade interface. The well reads on any colour: the five sheets are variables, from the palest on top to the darkest at the bottom.
The sidebar is 252 pixels wide and about 390 tall: at 390 pixels it fits whole on the screen. With a finger down on a link the top sheet opens its tray, as with the mouse over it, and the tap chooses it.
No sliding holes and no tray: choosing another link the well appears already dug under it, in a short fade. When the page opens the sidebar fades in with the well already in place.
GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.0 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.