
The graph paper background
Backgrounds, Scroll
NewFree
Scroll inside the preview
A background to scroll through, in minimal style: on an almost pure black, two sources of circular waves drawn only as thin crests, like two stones in a pond seen from above. As you scroll the sources move apart and the interference pattern opens up: the crests light up where they add up and vanish on the lines of silence, and a thread of light runs along the fringes. The pointer is a third, vermilion source, and a tap flips its phase.
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>Antinode</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist@5.3.0/wght.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- a long section with a sticky stage: two sources of circular waves, drawn as thin crest lines on a canvas;
scrolling moves the sources apart and the interference pattern changes; the pointer is a third, weak source -->
<main class="corsa" data-corsa>
<section class="palco" data-palco>
<canvas class="onde" aria-hidden="true" data-onde></canvas>
<header class="testa">
<p class="marchio" data-entra>Antinode</p>
<p class="testa__nota" data-entra>Acoustic design studio</p>
</header>
<div class="frasi" aria-live="polite">
<p class="frase" data-frase><span class="frase__occhio">One source</span><span class="frase__testo">Every sound starts as a ring.</span></p>
<p class="frase" data-frase><span class="frase__occhio">Two sources</span><span class="frase__testo">Where crests meet, it grows.</span></p>
<p class="frase" data-frase><span class="frase__occhio">Further apart</span><span class="frase__testo">Where they cross, silence.</span></p>
</div>
<footer class="piede">
<p class="piede__nota" data-entra data-cenno>Scroll to part the sources, tap to flip your own</p>
<p class="piede__lettura" aria-hidden="true" data-entra>
<span class="lettura__nome">Spacing</span>
<span class="lettura__valore" data-distanza>0.0</span>
<span class="lettura__unita">λ</span>
<span class="lettura__fase" data-fase>In phase</span>
</p>
</footer>
</section>
</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.
27 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 interference waves background on scroll” from Animorio and fit it into my siteThe section is 420lvh tall and the stage inside is sticky, 100lvh tall. A ScrollTrigger reads the progress from 0 to 1 (with Lenis for smooth scrolling) and gives the wanted spacing between the sources: together for the first 14%, then they separate on a smooth curve up to APERTURA wavelengths. The real spacing follows it on a spring, so the pattern never jumps.
Each source draws its rings one wavelength apart, moving outwards at VELOCITA waves per second. Each ring is made of 7 px pieces; those outside the stage are skipped. The amplitude fades slowly with distance (1 over the square root of 1 + r / 3.4 wavelengths) and at the opening a soft edge runs outwards: before it arrives there is nothing.
Two equal waves reaching a point along paths r1 and r2 add up to 2 cos(k (r1 − r2) / 2). Each piece takes the absolute value raised to the power 1.6 as its light, and ends up in one of four bunches of light and width: four paths, four strokes per source. Where the value drops to zero the crests vanish: those are the lines of silence.
The points where the path difference is a whole number of wavelengths lie on hyperbolas with their foci on the sources: x = a cosh u, y = b sinh u, with a half the difference and b² = c² − a². They are drawn as a single faint path, then again with a 7 px dash every 88 whose start moves forward FLUSSO px per second.
The pointer is a third source on a spring (MOLLA), with strength PUNTATORE: its rings are drawn in vermilion and fade away from it. A pointerdown takes its phase from 0 to π, or back, with elastic.out in 0.9 s: the rings slide by half a wave and go just past. Every new sentence and every tap send a brighter wave out of the sources. After 2.4 s without the real pointer, a fake source follows a slow curve.
| Name | File | Default | What it changes |
|---|---|---|---|
ONDA | script.js | 0.07 | The wavelength, as a fraction of the stage’s short side. |
VELOCITA | script.js | 0.55 | How many waves per second leave each source. |
APERTURA | script.js | 5.5 | How far apart the sources end up at the end of the run, in wavelengths. |
PUNTATORE | script.js | 0.6 | How strong the pointer’s source is compared with the other two. |
FLUSSO | script.js | 38 | How fast the light runs along the fringes, in px per second. |
MOLLA | script.js | [70, 12] | The spring of the pointer’s source: how stiff and how damped. |
SPESSORE | script.js | 1 | The thickness of the crests nearest the sources, in px. |
As a background to scroll through for an acoustics or sound design studio, a concert hall, a speaker or headphone company, a physics lab or a science museum, a page that tells a product in steps; in general behind short sentences when you want a dark background that changes as you go down. The line colour and the accent are set in the CSS.
The same animations with the sizes adapted: the wavelength is measured on the short side, and on a tall stage the sources separate vertically, so the pattern fills the whole box. The finger moves the third source and a tap flips its phase; the page still scrolls vertically.
The pattern is still, with the sources at half their spacing and no pointer source: no spreading rings, no thread of light, no brighter waves. The sentences change on scroll with a fade.
GSAP 3.15.0, ScrollTrigger 3.15.0, Lenis 1.3.26, Geist (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.4 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.