Skip to content
animorio
IT
Back to the library

The lighthouse in the storm

Scroll, SVGGSAPAdvancedCompressed weight: Demo 14 KBGSAP + ScrollTrigger 45 KBLenis 5.3 KBFreeDownload the zip

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.

The code

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>

Playground

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

Or ask Claude Code for it

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 site

What it does

The page of a made-up sea rescue charity, Gullstone Sea Rescue. The stage stays still for nine screens and the scroll is the time of one night. At the top it is evening: a violet and peach sky, the sun touching the sea, the red and white striped lighthouse on its rock, and on the left a quay with three houses and a green harbour light. As you scroll, clouds come in from both sides and close the sky, sky and sea turn dark, the four rows of waves rise and the crests grow sharp and white with foam; when a wave reaches the rock a burst of spray flies up, and the same happens against the quay. The rain starts, bent by the wind, and halfway through the storm comes the lightning: the bolt draws itself from top to bottom, the scene lights up twice and everything shakes. All the while the lighthouse turns: two opposite beams grow and shrink as if they were really spinning, and when they face the viewer the lantern glares. On the horizon an orange rescue boat appears; the beam stops turning, finds it and follows it as it fights the waves, moves forward, gets pushed back, sets off again and reaches the quay, larger and larger as it comes closer. Then the wind drops, the rain stops, the clouds leave to the right, the lighthouse switches off, the morning sun rises, a rainbow draws itself and the gulls arrive. The windows of the houses light up in the night and go dark in the morning; the lines change at every moment of the story, word by word, and in the morning the text turns dark against the bright sky.

How it works

The stage and the story

The 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.

Gerstner waves

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 turning beam

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 coming closer

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.

Rain, spray and lightning

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.

Values to change

NameFileDefaultWhat it changes
STORMscript.js1How high the waves rise in the storm: 0.3 choppy sea, 1.6 a full gale.
RAINscript.js160How many drops fall at the worst moment.
RAIN_ANGLEscript.js22How many degrees the wind bends the rain: 0 falls straight.
BEAM_SPEEDscript.js1How many turns the lighthouse beam makes every five seconds.
FOAMscript.js1How much spray flies off the rock and the quay when a wave arrives: 0 no spray.
LIGHTNINGscript.jstrueThe lightning halfway through the storm: false turns it off.
--cielo-tempesta-altostyle.css#0b1018The storm sky; next to it are the evening and morning skies, the sea, the clouds, the lighthouse and the boat.

Try them in the Playground

When to use it

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.

On phones

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.

With reduced motion

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.

Pitfalls

  • With Gerstner waves, if steepness times amplitude times wave number goes past 1 the crest points overtake each other and the curve loops. The steepness is clamped to 0.92/(A·k) every frame, so the gale stays sharp without tying knots.
  • Lightning tied to the scroll with scrub lasts as long as you take to scroll: scrolling slowly left the sky white for seconds. The lightning is a timed timeline that starts when the scroll passes the right point.
  • The beam aiming at the boat jumped to the other side of the lighthouse when the angle went from 179 to -179 degrees. It moves towards the boat the shortest way round, with the difference between the angles brought back between -180 and 180.
  • Text with a text-shadow inside the revealing words (overflow: hidden) showed the shadow clipped into boxes around each word. No shadow: in the morning the text colour moves from light to dark together with the sky.
  • Spray with a lot of sideways speed ended up in the middle of the sea like confetti far from the rock. It now leaves almost straight up, lives just over half a second and falls with gravity.

Libraries

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.

Testing

Tested on 10 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

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.

All animations