
Standing letters with a long shadow
Text, Scroll, 3D
NewFree
Scroll inside the preview
The big opening title is wrapped around a 3D cylinder that turns as you scroll, with the letters darker on the sides and at the back. Then the cylinder unrolls like a carpet: the letters come off one after the other and settle in a straight line, with a small elastic bounce. Further down a second title does the opposite: it rolls up, spins and leaves.
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 title wrapped on a cylinder</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- the opening of a made-up magazine about clay. The big title is wrapped on a turning cylinder, like the words
painted around a pot on the wheel; scrolling turns it, then unrolls it letter by letter into a straight line.
Further down a second title does the opposite: it rolls up and leaves -->
<header class="testata">
<a class="testata__marchio" href="#">Slip</a>
<p class="testata__uscita">The autumn issue</p>
<nav class="testata__nav" aria-label="Sections">
<a class="rullo" href="#"><span data-t="Stories">Stories</span></a>
<a class="rullo" href="#"><span data-t="Studios">Studios</span></a>
<a class="rullo" href="#"><span data-t="Glazes">Glazes</span></a>
</nav>
</header>
<main>
<section class="giro" data-giro>
<div class="palco">
<p class="occhiello" data-occhiello>A quarterly on clay and the hands that shape it</p>
<div class="cilindro" data-cilindro>
<h1 class="nascosto" data-titolo></h1>
<div class="anello" data-anello aria-hidden="true"></div>
</div>
<div class="sommario" data-sommario>
<p class="sommario__testo" data-riga>Seven potters, one studio by the river, and the slow afternoons it takes to centre a ball of clay.</p>
<p class="sommario__firma" data-riga>Words by Ines Moreau. Photographs by Tomas Leer.</p>
</div>
<p class="invito" data-invito>
<span>Scroll to unroll</span>
<svg viewBox="0 0 12 18" aria-hidden="true"><path d="M6 1v15M1.5 11.5 6 16l4.5-4.5" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/></svg>
</p>
</div>
</section>
<article class="pezzo">
<div class="pezzo__testo">
<p class="pezzo__primo" data-sale>The wheel at the back of the studio is older than anyone who uses it. It hums when it starts, settles into a low note, and from then on the only sound is water and the soft slap of a palm on wet clay.</p>
<p data-sale>Centring comes first, and it never gets quicker. You lean in with the whole body, not the arms, until the lump stops fighting you and spins without a wobble. Only then does the hole open, and the walls begin to rise.</p>
<blockquote class="citazione" data-sale>
<p>The clay tells you when it is ready. You just have to stop talking.</p>
</blockquote>
<p data-sale>Every pot here carries a line of words painted around its belly before the first firing: a name, a date, a line from a song. Turn the pot and the sentence comes round to meet you.</p>
</div>
<figure class="vaso" aria-hidden="true">
<svg viewBox="0 0 240 320">
<path data-traccia d="M88 30h64M92 30c0 22-6 34-22 56-18 25-34 52-34 92 0 62 36 112 84 112s84-50 84-112c0-40-16-67-34-92-16-22-22-34-22-56" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"/>
<path data-traccia d="M44 150c46 16 106 16 152 0M40 196c50 18 110 18 160 0" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
<path data-traccia d="M70 292h100M40 304h160" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/>
</svg>
<figcaption>Drawn in the studio, before the first firing</figcaption>
</figure>
</article>
<section class="forno" data-forno>
<div class="palco palco--forno">
<p class="occhiello occhiello--forno">Next, the firing</p>
<div class="cilindro" data-cilindro>
<h2 class="nascosto" data-titolo></h2>
<div class="anello" data-anello aria-hidden="true"></div>
</div>
<p class="forno__nota" data-nota>Twelve hours of heat, a night of cooling, and nobody opens the door before morning.</p>
</div>
</section>
<footer class="piede">
<p class="piede__marchio">Slip</p>
<p class="piede__testo">Four issues a year, printed on paper you can feel.</p>
<a class="pillola" href="#"><span class="pillola__fondo" aria-hidden="true"></span><span class="pillola__scritta">Subscribe</span></a>
</footer>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.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.
39 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 title wrapped on a cylinder” from Animorio and fit it into my siteThe script splits TITLE into letters, each in two spans: the scroll moves the outer one, the bounce the inner one. It measures the letters at 100 pixels, picks the size that fits the line in 84% of the window (90% on a phone, at most 26% of the height) and gives every letter its place s on the line, measured from the middle.
The radius is RADIUS times the length of the line divided by 2π: with 1 the title goes exactly once around. Wrapped, a letter sits at the angle s / R: x = R · sin a, z = R · cos a − R, and rotateY(a) turns it outwards. Behind the letters, 24 to 72 narrow clay bands make the surface. The wrapped cylinder sits a little closer to you (a share of the perspective), so it looks bigger, and TILT leans it with rotateX around its own axis.
The colour of every letter and band is mixed between the lit colour and the shaded one by the angle: (1 − cos a) / 2, a little more on the right side because the light comes from the left, and more again at the back. SHADE says how dark it gets. The letters at the back show backwards (backface-visibility visible) and faint, as if through the clay. The bands live in a layer of their own, under the letters, so a letter is never cut or covered by a band; when the unrolling starts the cylinder already stands upright, and each band vanishes as soon as it comes off.
The stage is a 100lvh sticky box in a 380lvh section; a tween with ScrollTrigger and scrub carries the progress from 0 to 1, and Lenis smooths the scroll. In the first half the cylinder turns TURNS times, slowing down; from 30% to 82% it unrolls. Every letter has its own stretch (one every 1 / 3.4 of the unrolling, from the left) in which position and angle go from the cylinder to the line with power3.inOut. Meanwhile the cylinder rolls to the right like a carpet and turns as much as it rolls, so the letter coming off always leaves from its left side.
When a letter lands on the line, the inner span starts squashed (scaleY 0.72, scaleX 1.16) and springs back with EASE in 1.1 seconds. The second title uses the same cylinder backwards: the unrolling goes from 1 to 0, so it rolls up from the right; then it spins faster and faster with power2.in, tilts, rises, shrinks and disappears.
| Name | File | Default | What it changes |
|---|---|---|---|
TITLE | script.js | 'On the wheel' | The opening title, wrapped on the cylinder. |
OUTRO_TITLE | script.js | 'Into the kiln' | The second title, the one that rolls up and leaves. |
RADIUS | script.js | 1.15 | The size of the cylinder: with 1 the title goes exactly once around it, more leaves a gap at the back. |
TURNS | script.js | 2 | How many times the cylinder turns before it unrolls (whole numbers start with the title in front). |
SHADE | script.js | 0.8 | How dark the letters get on the sides and at the back, from 0 to 1. |
TILT | script.js | 16 | How much you look down on the cylinder, in degrees. |
EASE | script.js | 'elastic.out(1.1, 0.35)' | The bounce of each letter when it lands in the straight line. |
SCRUB | script.js | 0.6 | The seconds the cylinder takes to catch up with the scroll. |
For the opening of a magazine, a long read, a project page or a brand that has to do with something that turns: ceramics, textiles, printing, records, cans, labels. It works with short titles, 6 to 16 letters: with a long sentence the line gets small and the cylinder huge.
The same animations with the sizes adapted: the line takes 90% of the width, the wrapped cylinder sits closer to you so it stays big on the narrow screen, and a finger unrolls the title like the wheel (Lenis leaves native scrolling to touch).
Nothing turns and nothing moves: the title is already straight in its place, the standfirst and byline fade in as soon as you scroll, and the second title fades away. Lenis does not start.
GSAP 3.15.0, Lenis 1.3.26, Fraunces (font variabile) 5.3.0, Instrument Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 9.6 KB; the libraries: GSAP + ScrollTrigger 45 KB, Lenis 5.3 KB.
Tested on 10 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.