
Keep scrolling
Transitions, Scroll
NewFree
Scroll inside the preview
A minimal-style scroll animation on a silver background: two thin rings, each with two crosshairs on its rim, change place, size and turn at every section. Between one section and the next they do not jump: first they regroup on the same circle in the middle, then they spread into the new layout. On the left a thin index with the names of the sections and a red line that fills as you scroll.
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>Raggio</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/hanken-grotesk@5.3.0/wght.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- a made-up maker of carbon wheels, Raggio. The stage sticks while you scroll: two thin rings, each with two
crosshairs on its rim, change place, size and turn at every stop. Between one stop and the next they first
regroup on the same circle in the middle, then spread to the new layout. On the left a thin index names the
sections and a line fills with the scroll -->
<main>
<section class="corsa" data-corsa>
<div class="palco" data-palco>
<div class="anelli" data-anelli aria-hidden="true">
<div class="anello" data-anello>
<span class="anello__tacca" data-tacca></span>
<span class="mirino mirino--a" data-mirino><svg viewBox="0 0 14 14"><path d="M7 0v14M0 7h14"/></svg></span>
<span class="mirino mirino--b" data-mirino><svg viewBox="0 0 14 14"><path d="M7 0v14M0 7h14"/></svg></span>
</div>
<div class="anello" data-anello>
<span class="anello__tacca" data-tacca></span>
<span class="mirino mirino--a" data-mirino><svg viewBox="0 0 14 14"><path d="M7 0v14M0 7h14"/></svg></span>
<span class="mirino mirino--b" data-mirino><svg viewBox="0 0 14 14"><path d="M7 0v14M0 7h14"/></svg></span>
</div>
</div>
<span class="angolo angolo--ns" aria-hidden="true"><svg viewBox="0 0 14 14"><path d="M7 0v14M0 7h14"/></svg></span>
<span class="angolo angolo--ne" aria-hidden="true"><svg viewBox="0 0 14 14"><path d="M7 0v14M0 7h14"/></svg></span>
<span class="angolo angolo--ss" aria-hidden="true"><svg viewBox="0 0 14 14"><path d="M7 0v14M0 7h14"/></svg></span>
<span class="angolo angolo--se" aria-hidden="true"><svg viewBox="0 0 14 14"><path d="M7 0v14M0 7h14"/></svg></span>
<a class="marchio" href="#" data-marchio>Raggio</a>
<nav class="indice" aria-label="Sections" data-indice>
<span class="indice__binario"><span class="indice__pieno" data-pieno></span></span>
<ul>
<li><a href="#" data-voce="1">Philosophy</a></li>
<li><a href="#" data-voce="2">Craft</a></li>
<li><a href="#" data-voce="3">Innovation</a></li>
<li><a href="#" data-voce="4">Ride</a></li>
</ul>
</nav>
<div class="titoli" data-titoli>
<div class="titolo" data-titolo>
<p class="titolo__nota">Carbon wheels</p>
<h2>Built around a circle</h2>
</div>
<div class="titolo" data-titolo>
<p class="titolo__nota">Philosophy</p>
<h2>Light is a decision</h2>
</div>
<div class="titolo" data-titolo>
<p class="titolo__nota">Craft</p>
<h2>Laid by hand, in carbon</h2>
</div>
<div class="titolo" data-titolo>
<p class="titolo__nota">Innovation</p>
<h2>Stiffer where it matters</h2>
</div>
<div class="titolo" data-titolo>
<p class="titolo__nota">Ride</p>
<h2>Made for the long climb</h2>
</div>
</div>
<p class="cenno" 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></p>
</div>
</section>
<footer class="piede">
<p>Raggio wheels are laid by hand, one rim at a time.</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.
32 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 section index with crosshair circles that regroup on scroll” from Animorio and fit it into my siteEvery stop is a pair of poses, one per ring: offset from the middle, diameter, turn and whether the crosshairs show. They are written in units of a 1080-high screen, as the original site does with its lvh measures: diameters of 900, 840, 754, 700, 678, side offsets of 234, 330, 346 (the last stop here at 300, to keep the index clear). The script multiplies them by the smaller of height / 1080 and width / 900, so on a phone the width decides and the rings never get too big.
A ScrollTrigger on the section reads the progress and works out the current stop and whether you are close to a change (ZONE, a share of a stop before and after). A small state machine does the rest: if the stop shown is not the right one, or you are close to a change, the rings first go to the shared circle in the middle, 840 across, in GATHER seconds; then, away from the change, they spread into the new stop in MOVE seconds. Even scrolling fast they always pass through the middle.
Every move uses cubic-bezier(.33, 0, 0, 1), the curve of the original site: it starts quickly and lands slowly. GSAP has no CSS curves, so it is solved by hand with a few Newton steps and passed as an ease function. The second ring starts LAG seconds after the first. Width and height are animated, not the scale, so the rim stays one pixel at every size.
The crosshairs are children of the ring and turn with it; when they arrive GSAP takes them from 0.4 to 1 with back.out and from minus 45 degrees to zero, then down by a pixel and up. The red tick is a box as big as the ring, turned by GSAP's ticker, faster when the scroll has speed. The index line is a scaleY equal to the progress; on a phone the index lies down under the headline and the line becomes a scaleX.
Pointing at a name (only with hover: hover) turns the group of rings LEAN degrees towards it and shifts it a little; a click takes you with Lenis to the middle of that stop. On every resize the poses in pixels are worked out again and set at once, even in the middle of a move, then the machine starts again.
| Name | File | Default | What it changes |
|---|---|---|---|
RIDE | script.js | 1 | How much scroll the five stops take: 2 is twice as long. |
GATHER | script.js | 0.8 | The seconds the rings take to regroup in the middle. |
MOVE | script.js | 1.2 | The seconds the rings take to spread into the next layout. |
LAG | script.js | 0.08 | The seconds between the first and the second ring. |
ZONE | script.js | 0.14 | How long the rings stay regrouped around a change, as a share of a stop. |
SIZE | script.js | 1 | How big the rings are: 1 is the measure of the layouts. |
LEAN | script.js | 7 | How many degrees the rings lean towards the name you point at. |
TICK | script.js | 1 | How fast the red tick runs along the rims. |
As the opening of a technical product page (wheels, bicycles, watches, instruments) split into chapters; as the index of a presentation or a company story in a few sections; wherever a precise, calm movement, like a technical drawing, is wanted behind short headlines.
The same animation: the layouts are sized on the width, so the rings stay in the stage and whatever goes past the sides is cut by the stage. The index lies down at the bottom, under the headline, and its line fills from left to right; a tap on a name takes you to the stop.
The rings do not travel: at every stop they fade out, change place and fade back in. The tick stays still, the headlines fade in, no smooth scrolling.
GSAP 3.15.0, ScrollTrigger 3.15.0, Lenis 1.3.26, Hanken Grotesk (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 24 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.