
Words that melt into each other
Text, Scroll, SVG
NewFree
Scroll inside the preview
A minimal-style scroll animation: a thin curve crosses the screen and a sentence rides along it, pushed by the scroll, swelling in the valleys and thinning on the crests. At the end the curve relaxes into a straight rule, the sentence settles on it like a headline and a red full stop drops in.
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>Meander</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/newsreader@5.3.0/opsz.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/newsreader@5.3.0/opsz-italic.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- a made-up magazine of slow travel, Meander. The stage sticks while you scroll: one thin curve crosses it from
edge to edge and a sentence rides along it, swelling in the valleys and thinning on the crests. At the end the
curve relaxes into a straight rule, the sentence settles on it like a headline and a red full stop drops in.
The curve and the letters are drawn by the script -->
<main>
<section class="corsa" data-corsa>
<div class="palco" data-palco>
<header class="testa">
<a class="marchio" href="#" data-entra>Meander</a>
<p class="testa__nota" data-entra>A magazine of slow travel</p>
</header>
<svg class="tela" data-tela aria-hidden="true">
<path class="curva" data-curva d="M0 0"/>
<g class="lettere" data-lettere></g>
<circle class="punto" data-punto r="4" cx="-99" cy="-99"/>
</svg>
<h1 class="solo-lettori" data-titolo>Take the long way round.</h1>
<p class="sotto" data-sotto>The autumn issue: twelve journeys on foot, by boat and by night train.</p>
<p class="cenno" data-entra><span>Scroll</span><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 3v13M4.5 10.5 10 16l5.5-5.5"/></svg></p>
</div>
</section>
<footer class="piede">
<p>Meander is printed four times a year, on uncoated paper, in a small town by the sea.</p>
</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.
21 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 sentence along the curve” from Animorio and fit it into my siteThe sentence is made of one SVG text per letter, not of a textPath: that way every letter can have its own weight and optical size, which textPath cannot change letter by letter. The advances are measured once at 100 pixels, for the two ends of the face, as the difference between the sentence cut after the letter and before it (with an n at the end, so the trailing space is not dropped): that keeps the kerning pairs like Ta and wa. In between they are interpolated.
The curve is a sine wave worked out at 360 points, from beyond the left edge to beyond the right one, with the arc length summed at every point. A binary search on that length gives, for every letter, the point where it stands and the direction of the curve there: the letter moves to that point and turns by that angle, centred on its advance. The curve itself is a path rebuilt on every frame from the same points. In the valleys every advance opens up with the curvature at that point, so the tops of the letters do not touch.
Newsreader’s weight and optical size move together on a single number, from 0 on the crest (weight 250, the fine display cut at opsz 72) to 1 in the valley (weight 740, the sturdy and wider cut at opsz 6). Each letter’s number depends on how low it sits on the curve, through a smoothstep, and font-variation-settings writes it inline. As the curve flattens the contrast drops and every letter moves towards the headline weight.
The stage is sticky and 100lvh tall inside a section about five screens long; Lenis smooths the scroll and a ScrollTrigger without a timeline reads the progress, which an exponential average chases once more (SMOOTH). From the progress come how far the sentence has travelled, how far the wave has drifted, how flat the curve is and how far its ends have drawn in. The depth of the wave follows a spring, which overshoots the straight rule by a pixel and settles. The full stop is a real timeline, not tied to the scroll: it plays when the progress passes 86% and goes back below 80%; falling with power2.in it squashes the circle and digs a two-pixel bell into the curve that comes back with elastic.out.
| Name | File | Default | What it changes |
|---|---|---|---|
PHRASE | script.js | 'Take the long way round' | The sentence that rides the curve (the full stop is the red dot). Short is better: on a phone it has to fit the width. |
WAVE | script.js | 0.17 | How deep the curve is, as a share of the screen height (on a phone it is capped, so the letters do not crowd on the crests). |
WAVES | script.js | 1.4 | How many waves cross the screen. |
LIGHT | script.js | 250 | The weight of the letters on the crests (200 to 800). |
HEAVY | script.js | 740 | The weight of the letters in the valleys (200 to 800). |
SETTLED | script.js | 470 | The weight of the sentence once it lies straight, as a headline. |
SIZE | script.js | 0.6 | How wide the settled sentence is, as a share of the screen (more on a phone); it is never taller than a sixth of the height. |
LINE | script.js | 1 | How thick the curve is, in pixels. |
SMOOTH | script.js | 5 | How quickly the sentence catches up with the scroll: less is softer. |
RIDE | script.js | 1 | How much scroll the whole thing takes: 2 is twice as long. |
For the opening line of a magazine, a travel agency, a story or a landing page: a motto to read as you scroll, which stays as the section headline at the end.
The same animation with the sizes adapted: the sentence is almost as wide as the screen, the wave keeps the wavelength of a computer screen (so it is gentler and the letters do not crowd) and the final rule stays inside the edges. Everything is worked out again if the window changes size, even halfway.
Nothing moves and the scroll is not smoothed: the sentence already lies straight on the rule, with the red dot and the line below, and fades in.
GSAP 3.15.0, ScrollTrigger 3.15.0, Lenis 1.3.26, Newsreader (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.5 KB; the libraries: GSAP + ScrollTrigger 45 KB, Lenis 5.3 KB.
Tested on 21 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.