
Words that melt into each other
Text, Scroll, SVG
NewFree
Scroll inside the preview
A lighthouse on a rock at sunset. As you scroll the weather turns: the clouds close in, the waves rise and break into foam, the rain falls sideways and a bolt of lightning splits the sky. The lighthouse beam turns, finds a rescue boat among the waves and walks it home to the harbour. Then the storm passes and the sky clears, with the sun, a rainbow and the gulls.
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>A lighthouse in the storm</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="scena" data-scena>
<div class="palco" data-palco>
<!-- il mare, il faro, la barca, la pioggia: lo script li disegna su misura dello schermo -->
<svg class="mare" data-mare aria-hidden="true" focusable="false"></svg>
<div class="lampo" data-lampo aria-hidden="true"></div>
<header class="testata">
<p class="marchio">
<svg class="marchio__segno" viewBox="0 0 32 32" aria-hidden="true" focusable="false"><path d="M12.5 12h7l2 16h-11z" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linejoin="round"/><path d="M11 12h10M13 6.5h6V12h-6zM16 3v3.5" fill="none" stroke="currentColor" stroke-width="2.6" stroke-linejoin="round" stroke-linecap="round"/><path d="M4 28h24" stroke="currentColor" stroke-width="2.6" stroke-linecap="round"/></svg>
<span>Gullstone Sea Rescue</span>
</p>
<a class="dona" href="#"><span class="dona__fondo" aria-hidden="true"></span><span class="dona__testo">Donate</span></a>
</header>
<section class="racconto" data-racconto aria-live="polite"></section>
<p class="cenno" data-cenno>Scroll into the storm</p>
</div>
</main>
<!-- il racconto: da che punto della discesa (0-1) vale ogni riga -->
<ul class="capitoli" data-capitoli hidden>
<li data-da="0" data-nome="Seven in the evening">Most nights, the sea is kind.</li>
<li data-da="0.1" data-nome="Nine o'clock">Some nights, it isn't.</li>
<li data-da="0.3" data-nome="Midnight">Force nine. Rain sideways. A boat past the rocks.</li>
<li data-da="0.44" data-nome="The light">We keep the light turning until it finds them.</li>
<li data-da="0.66" data-nome="Four in the morning">Every crew home. Every time.</li>
<li data-da="0.82" data-nome="Morning">Volunteers on call since 1897. Join the watch.</li>
</ul>
<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.
33 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 lighthouse in the storm” from Animorio and fit it into my siteThe scene is nine screens tall and holds a sticky stage 100lvh tall with an SVG as big as the stage: the viewBox is its size in pixels. A single tween with ScrollTrigger (scrub 0.8) carries a number from 0 to 1 along the whole scroll; every frame that number becomes the progress of a paused timeline, the story, which moves a handful of values: clouds, storm, rain, boat, beam lock, clear sky, rainbow, gulls.
Every row of waves is a path rebuilt every frame: one point every 9 pixels, moved up and down by a cosine and sideways by a sine. The sideways shift squeezes the points on the crest, which grows sharp, as in Gerstner waves; the storm raises the amplitude and the steepness, kept under the limit where the curve would fold over itself. Over every crest high enough a thick white stroke makes the foam, spilling down the front of the wave.
The lighthouse turns in a plane we see edge on: for two opposite beams the cosine of the angle says which way they point and how long they look on screen. When the cosine is close to zero the beam faces us and the lantern glares. The cones have a gradient that fades into the distance and mix-blend-mode: screen, so they brighten the sky, the rain and the boat they touch. When the boat arrives, the angle moves towards it the shortest way round and the beam follows it.
The boat travels from a point on the horizon to the quay through a chain of tweens on the same number: forward, back a little with power2.out, forward, back again and finally into harbour. The closer it gets the bigger it grows, and its height is a blend of the far and near rows of waves, read at the right point with a binary search. It tilts with the slope of the wave, a bit more in the storm; the flag on the mast flutters.
The rain is a single path holding every drop, bent by the wind: it costs as much as one line. The spray is circles with speed and gravity, thrown when a wave crest reaches the rock or the quay. The lightning is a small timed timeline (not tied to the scroll) that starts when the scroll passes 33%: the bolt draws itself with stroke-dashoffset, a pale veil flashes twice and the SVG shakes with elastic.out.
| Name | File | Default | What it changes |
|---|---|---|---|
STORM | script.js | 1 | How high the waves rise in the storm: 0.3 choppy sea, 1.6 a full gale. |
RAIN | script.js | 160 | How many drops fall at the worst moment. |
RAIN_ANGLE | script.js | 22 | How many degrees the wind bends the rain: 0 falls straight. |
BEAM_SPEED | script.js | 1 | How many turns the lighthouse beam makes every five seconds. |
FOAM | script.js | 1 | How much spray flies off the rock and the quay when a wave arrives: 0 no spray. |
LIGHTNING | script.js | true | The lightning halfway through the storm: false turns it off. |
--cielo-tempesta-alto | style.css | #0b1018 | The storm sky; next to it are the evening and morning skies, the sea, the clouds, the lighthouse and the boat. |
For anyone telling a story of protection or rescue: a rescue charity, an insurance company, a fundraiser, an emergency service, a sailing or rainwear brand, or any story that goes from danger to calm as it is read.
The same animation with the sizes adapted: smaller lighthouse, boat, houses and waves, the horizon a little lower to leave room for the text at the top, the quay wider in proportion, the bolt between the text and the lighthouse. The scroll is still nine screens.
No running waves, no falling rain, no spray, no turning beam, no flashing lightning and no smooth scrolling: the story stops on six still pictures, one for each line of text, and fades from one to the next. In the storm picture the bolt is there, drawn and still.
GSAP 3.15.0, Lenis 1.3.26, Mona Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 14 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.