
Words that melt into each other
Text, Scroll, SVG
NewFree
Scroll inside the preview
A furniture workshop’s story told by the oak planted the year it opened, in the minimal style: as you scroll, the cross-section of the trunk grows one ring a year under its bark, wide in the good years and narrow in the dry ones, while the year counts. The years that mattered are vermilion rings, marked on a thin ruler from the pith to the bark, and they change the note under the year.
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 rings of the trunk</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/newsreader@5.3.0/opsz.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- the story of a made-up furniture workshop, Alder, told by the oak planted the year it opened. Scrolling, the
cross-section of the trunk grows one ring a year under its bark, from the pith outwards, while the year counts;
the years that mattered are drawn in vermilion and written on a thin radial ruler -->
<main>
<section class="apertura">
<p class="piccolo">Alder, furniture workshop</p>
<h1 class="titolo">The oak in our yard<br>keeps the books.</h1>
<p class="piccolo piccolo--tenue">Scroll to count the rings.</p>
</section>
<section class="racconto" data-racconto>
<div class="palco" data-palco>
<header class="testa">
<p class="marchio">Alder</p>
<p class="piccolo piccolo--tenue">One ring a year</p>
</header>
<svg class="tronco" data-tronco aria-hidden="true"></svg>
<div class="conto">
<p class="anno" data-anno>1962</p>
<p class="nota" data-note aria-live="polite"></p>
</div>
</div>
</section>
<section class="apertura apertura--fine">
<h2 class="titolo titolo--medio">Every table we make<br>is a few of these rings.</h2>
</section>
</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="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.
24 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 rings of the trunk” from Animorio and fit it into my siteThe widths of the rings come from a small seeded random number generator (SEED): the same seed always grows the same tree. Each width is a slow climate (two sine waves, the good decades and the dry ones) times the noise of the year, and it drops with age as in real trees. The running sums give the radius of every ring, from the pith’s up to 1.
Each ring is a path of 144 points: the radius times 1 plus three sine waves (one, two and three waves per turn) that all the rings share, plus a small wave of its own. The first one moves the centre, like the off-centre pith of a real trunk; the others squash it. WOBBLE says how much. The paths start from the ruler’s angle, so every ring draws itself from there.
The timeline, tied to the scroll with scrub SCRUB, carries a number y from 0 to the number of years. Each ring has pathLength 1 and stroke-dasharray 1 1: its stroke-dashoffset goes from 1 to 0 while y passes through its year, drawing it round. The bark is a single path at full size, scaled every frame to the ring being drawn, with vector-effect non-scaling-stroke so the line stays thin.
NOTES holds the notes by year: the years between the first and the last become vermilion rings, with a tick and the year on the ruler. The labels have an outline in the paper colour painted underneath (paint-order: stroke), so they read over the rings. The big figure takes weight for three years after each note, and the new note rises from below an overflow hidden window while the old one leaves upwards.
At the last year a second value of the timeline widens the bark by 1.2 per cent and lets it come back with elastic.out, while the year takes a little more weight with a back.out. Centre, radius and the place of the year are worked out again on every ScrollTrigger refresh and on every resize.
| Name | File | Default | What it changes |
|---|---|---|---|
FROM | script.js | 1962 | The year the tree was planted: the pith. |
TO | script.js | 2026 | This year: the ring under the bark. |
NOTES | script.js | { 1962: …, 1975: …, 1991: …, 2008: …, 2026: … } | The notes, by year: the years between the first and the last become vermilion rings on the ruler. |
WOBBLE | script.js | 0.07 | How far the rings are from a perfect circle. |
SEED | script.js | 7 | Change it for another tree (wide and narrow rings in other years). |
SCRUB | script.js | 0.6 | How many seconds the drawing takes to catch up with the scroll. |
For the «our story» page of a craft shop, a woodworker, a winery, a plant nursery or any business with a few decades behind it: the years really go by under your eyes and the important ones stay marked. It also works for an anniversary.
The same, with adapted measures: the trunk sits centred near the top, the year and the note below, and the rings have a finer line because they are closer together.
The trunk does not grow before your eyes: one still picture per note (1962, 1975, 1991, 2008, 2026) with all the rings up to that year, taking turns with a cross-fade; the notes cross-fade and there is no elastic at the end.
GSAP 3.15.0, ScrollTrigger (GSAP) 3.15.0, Newsreader (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 6.7 KB; the libraries: GSAP + ScrollTrigger 45 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.