
The falling letter
Scroll, Text, Transitions
NewFree
Scroll inside the preview
A thin horizon line and a solid sun: as you scroll the sun sets behind the line, flattens a little when it is low and leaves a stroke of its light on the line; then the night opens out of the line and the page goes from warm white to black. The greeting changes word by word, Good morning, Good evening, Good night, the letters sinking behind the same line, and the hours roll by beside it. Minimal style.
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 sun behind the line</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/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- a made-up seaside hotel, Vespera. The stage sticks while you scroll: one thin horizon line and a round sun.
The sun goes down behind the line, the greeting changes word by word sinking behind the same line, the hours
roll by on the right, and when the last light is gone the night opens out of the line and turns the page
black. The night is a second copy of the scene, made by the script -->
<main>
<section class="corsa" data-corsa>
<div class="palco" data-palco>
<div class="scena" data-scena>
<div class="cielo" data-cielo><div class="sole" data-sole></div></div>
<div class="orizzonte" data-orizzonte></div>
<div class="luce" data-luce></div>
<h1 class="titolo" data-titolo>Good morning</h1>
<div class="ore" data-ore aria-hidden="true"><div class="ore__nastro" data-nastro></div></div>
<p class="nota" data-nota>A small hotel by the sea, twelve rooms facing the sunset.</p>
<header class="testa">
<a class="marchio" href="#" data-marchio data-entra-testa>
<svg class="marchio__segno" viewBox="0 0 26 16" aria-hidden="true">
<svg x="0" y="0" width="26" height="13" overflow="hidden"><circle data-marchio-sole cx="13" cy="13" r="6"/></svg>
<path d="M1 13.5h24"/>
</svg>
<span class="marchio__nome">Vespera</span>
</a>
<a class="pillola" href="#" data-pillola data-entra-testa><span class="pillola__fondo" data-pillola-fondo></span><span class="pillola__testo">Book a room</span></a>
</header>
<p class="cenno" data-entra-testa><span class="cenno__dentro" data-cenno><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></span></p>
</div>
</div>
</section>
</main>
<!-- an invisible copy of the title, to measure it -->
<div class="misura" data-misura aria-hidden="true"></div>
<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.
22 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 sun behind the line” from Animorio and fit it into my siteA section seven screens tall and inside it a sticky stage 100lvh tall. The horizon line is a div one pixel tall, placed on a whole pixel (Math.round) so it stays sharp. The sky is a box that reaches down to the line with overflow hidden: the sun lives inside it, so going below the line it disappears on its own, with no masks. The title is also cut with clip-path exactly at the line, and the letters that go down pass behind it.
The sun’s position is a number from 0 to 1 in a state object, moved by the timeline with the scroll: the script turns it into pixels on every frame, so resizing the window breaks nothing. When the bottom of the sun is less than a radius from the line, scaleY drops to 1 − SQUASH, with the square of the distance: it is the flattening of the real sun near the horizon. The vermilion stroke on the line is as wide as the circle’s chord at the height of the line (2·√(R² − d²)) and, after sunset, stays a diameter wide until its light goes out.
The night is the same scene cloned with cloneNode, with the colour variables swapped and on top of the first. At the start clip-path closes it to nothing; opening, it becomes inset(top 0 bottom 0) with the two edges starting at the line and moving to the margins. Everything that moves (letters, sun, hours) moves together in both copies: GSAP’s lists hold both copies and the stagger is a function that counts inside one copy only (i % n).
The words every greeting shares (Good) stay; the rest of each greeting sits in a grid with a single cell, so the words lie on top of each other. The old word goes down by yPercent 135 with power2.in and font-variation-settings thins it, the new one comes up with back.out(0.6), that is a pixel or two too far. Each greeting has SOFT and wght a little higher than the one before. The title is measured on an invisible copy, at the weight of each greeting: on a phone it goes onto two lines.
The ruler is a strip of ticks built by the script and moved with translate3d so that the hour of the moment falls on the horizon; the labels close to the line get opacity and weight. Everything is one timeline with ScrollTrigger and scrub, with Lenis for smooth scrolling. The clock runs fast until sunset and slower afterwards. The state is redrawn in GSAP’s ticker only when something has changed; the final hop and the hover ones are timed tweens with elastic.out.
| Name | File | Default | What it changes |
|---|---|---|---|
GREETINGS | script.js | ['Good morning', 'Good evening', 'Good night'] | The greetings of the day, in order: the first words they share stay still, the rest changes by sinking behind the line. The first change comes when the sun touches the horizon, the last when the night opens. |
FIRST_HOUR | script.js | 10 | The hour at the top of the page, on the ruler. |
LAST_HOUR | script.js | 23 | The hour at the bottom of the page, the one that lights up at the end. |
HORIZON | script.js | 0.64 | How far down the horizon is, as a share of the screen height. |
SUN_SIZE | script.js | 1 | How big the sun is; the title gets smaller to stay beside it. |
SQUASH | script.js | 0.06 | How much the low sun flattens as it touches the line (0 = it stays round). |
LAST_LIGHT | script.js | 1 | How long the stroke of last light stays on the line after sunset (0 = none). |
RIDE | script.js | 1 | How much scrolling the whole thing takes: 2 is twice as much. |
--sole | style.css | #ff4b1f | The colour of the sun, of the last light and of the hour that lights up. |
--notte | style.css | #0c0c0b | The colour of the page at night. |
For the opening of a hotel, a holiday home or a restaurant with a terrace facing the sunset: a page that says “this is how the day ends here”. It also suits a site that changes with the hours, an event at sunset, or a move from a light section to a dark one.
The same: the greeting goes onto two lines, with the changing word resting on the line, the sun is a little smaller and the ruler of the hours narrower. Everything else moves the same way.
Nothing goes down or opens and Lenis stays off: the scroll goes through three stops, the day with the sun high, the sunset with the sun half behind the line and the night, and between one stop and the next the scene changes with a fade.
GSAP 3.15.0, ScrollTrigger 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 10 KB; the libraries: GSAP + ScrollTrigger 45 KB, Lenis 5.3 KB.
Tested on 15 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.