
La cornice che diventa la pagina
Transizioni, Scroll, SVG
NuovaGratis
Scorri dentro l’anteprima
Il mare di notte riempie lo schermo, e in mezzo c’è una finestra a forma di maschera da sub: dentro si vede l’acqua, con i pesci e la luce. Scorrendo, tutta la superficie cresce dal centro della maschera fino a venti volte e si sfoca, finché la finestra diventa lo schermo e sei sott’acqua.
Una cartella che funziona da sola: index.html, style.css, script.js e le librerie da CDN. Nelle schede React e Vue la stessa demo è già un componente, che spegne le sue animazioni quando esce dalla pagina.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The mask that opens</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/space-grotesk@5.3.0/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/instrument-serif@5.3.0/400-italic.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="bar">
<a class="brand" href="#">Lowtide Dive Club</a>
<nav class="bar__nav" aria-label="Sections">
<a href="#">Courses</a>
<a href="#">Sites</a>
<a href="#">Gear</a>
</nav>
</header>
<!-- one pinned screen with two worlds: under the water at the back, the night surface in front of it -->
<section class="dive" data-dive>
<!-- under the water: seen through the mask at the start, the whole screen at the end -->
<div class="deep" data-deep>
<svg class="deep__art" viewBox="0 0 1440 900" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
<defs>
<linearGradient id="water" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#5fe0d0"/>
<stop offset="0.45" stop-color="#1fa6b8"/>
<stop offset="1" stop-color="#0b4f74"/>
</linearGradient>
<linearGradient id="ray" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#ffffff" stop-opacity="0.55"/>
<stop offset="1" stop-color="#ffffff" stop-opacity="0"/>
</linearGradient>
</defs>
<rect width="1440" height="900" fill="url(#water)"/>
<g class="rays" data-rays>
<path d="M470 0h90l-150 900h-170z" fill="url(#ray)" opacity="0.6"/>
<path d="M700 0h60l40 900h-190z" fill="url(#ray)" opacity="0.45"/>
<path d="M930 0h110l230 900h-200z" fill="url(#ray)" opacity="0.5"/>
</g>
<!-- fish: each one swims across on its own line -->
<g data-fish fill="#f6b43c">
<path d="M0 0c22-16 52-16 72 0-20 16-50 16-72 0zm72 0 22-14v28z"/>
</g>
<g data-fish fill="#ff7a59">
<path d="M0 0c16-11 38-11 52 0-14 11-36 11-52 0zm52 0 16-10v20z"/>
</g>
<g data-fish fill="#fff1c9">
<path d="M0 0c14-9 32-9 44 0-12 9-30 9-44 0zm44 0 13-8v16z"/>
</g>
<g data-fish fill="#f6b43c">
<path d="M0 0c19-13 44-13 61 0-17 13-42 13-61 0zm61 0 19-12v24z"/>
</g>
<!-- the sea floor: two hills and a few weeds that sway -->
<path d="M0 790c180-60 330-40 470 0s320 40 520-10 330-40 450 10v110H0z" fill="#083a57"/>
<g class="weeds" fill="none" stroke="#0e6b62" stroke-width="10" stroke-linecap="round">
<path data-weed d="M180 860c-10-60 20-110 0-170"/>
<path data-weed d="M230 870c10-50-20-90 0-140"/>
<path data-weed d="M1150 860c-12-70 22-120 0-190"/>
<path data-weed d="M1210 870c8-50-16-80 0-120"/>
</g>
</svg>
<div class="deep__words">
<h1 class="deep__title" data-title>Below the surface, <em>everything slows down.</em></h1>
<a class="deep__link" href="#" data-cta>Book a first dive</a>
</div>
</div>
<!-- the surface at night, with a window in the shape of a diving mask; scrolling makes it grow until you are in -->
<div class="surface" data-surface>
<svg class="surface__art" viewBox="0 0 1440 900" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
<defs>
<linearGradient id="night" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#0a1430"/>
<stop offset="0.55" stop-color="#162a52"/>
<stop offset="1" stop-color="#0b1834"/>
</linearGradient>
<radialGradient id="glow" cx="0.5" cy="0.5" r="0.5">
<stop offset="0" stop-color="#fff6dc" stop-opacity="0.5"/>
<stop offset="1" stop-color="#fff6dc" stop-opacity="0"/>
</radialGradient>
<!-- the window: everything is drawn except the glass of the mask -->
<mask id="window" maskUnits="userSpaceOnUse" x="0" y="0" width="1440" height="900">
<rect width="1440" height="900" fill="#fff"/>
<use href="#lens" fill="#000"/>
</mask>
<path id="lens" data-lens d="M-96-34c0-20 16-26 36-26h120c20 0 36 6 36 26v48c0 26-18 42-44 42-16 0-26-8-34-20-6-10-12-14-18-14s-12 4-18 14c-8 12-18 20-34 20-26 0-44-16-44-42z" transform="translate(720 450) scale(1.15)"/>
</defs>
<g mask="url(#window)">
<rect width="1440" height="900" fill="url(#night)"/>
<circle cx="1080" cy="190" r="120" fill="url(#glow)"/>
<circle cx="1080" cy="190" r="34" fill="#fff4d8"/>
<path d="M0 560h1440v340H0z" fill="#0d2347"/>
<g class="waves" fill="none" stroke-linecap="round">
<!-- the script draws the waves: a line that goes up and down every 360 units, long enough to drift -->
<path data-wave data-y="610" data-amp="16" stroke="#24467a" stroke-width="5"/>
<path data-wave data-y="690" data-amp="20" stroke="#1d3c6c" stroke-width="7"/>
<path data-wave data-y="790" data-amp="24" stroke="#173462" stroke-width="9"/>
</g>
<!-- the rubber frame of the mask, around the glass -->
<use href="#lens" fill="none" stroke="#1b2333" stroke-width="22"/>
<use href="#lens" fill="none" stroke="#3a4a66" stroke-width="3"/>
</g>
</svg>
<div class="surface__words">
<p class="surface__lead" data-lead>Put the mask on.</p>
<p class="surface__hint">Scroll to go under.</p>
</div>
</div>
</section>
<section class="after">
<p class="after__text">Small groups, slow dives, and a warm drink on the boat on the way back.</p>
</section>
<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="script.js"></script>
</body>
</html>Cambia valori, colori e testi con le manopole e guarda l’animazione rispondere dal vivo. Oppure scrivi tu nel codice. Poi scarica la cartella con le tue modifiche.
22 valori da cambiare
Col connettore di Animorio, Claude Code la prende da qui con tutta la sua guida e la adatta al tuo progetto. Incolla questa richiesta:
Prendi «La maschera che si apre» da Animorio e adattala al mio sitoUno schermo fermo con due strati: dietro l’acqua, davanti la superficie. Sono due SVG con lo stesso viewBox, 1440 per 900, e preserveAspectRatio slice: coprono lo schermo allo stesso modo e il centro del disegno è sempre il centro dello schermo.
La superficie è disegnata sotto una mask SVG: un rettangolo bianco, che lascia vedere tutto, e la forma del vetro della maschera in nero, che fa il buco. La stessa forma, ridisegnata con un tratto scuro e spesso, è il bordo di gomma. Il vetro sta al centro del disegno.
Un ScrollTrigger ferma lo schermo per LENGTH altezze e con lo scrub porta un valore da 0 a 1. La superficie cresce dal centro e si sfoca con filter: blur(BLUR · valore px), la sfocatura dell’originale. La crescita no: l’originale va in linea retta, scala 1 + 19t, ma con una finestra grande come questa lo schermo sarebbe pieno nel primo quarto del tuffo. Qui la scala è (1 + GROW) elevato al valore, cioè cresce dello stesso fattore a ogni passo e la finestra si apre allo stesso ritmo fino in fondo, venti volte alla fine. È un solo strato, che il browser muove sulla scheda grafica. Fra i due punti di FADE la superficie sfuma; l’acqua passa da 1,12 a 1.
La frase della superficie è divisa in parole, ognuna dentro uno span che taglia quello che esce: al primo tocco dello scorrimento salgono (yPercent −110, power3.out, 0,04 secondi l’una dall’altra), come le parole SplitText dell’originale. A 0,72 del tuffo arrivano il titolo e il bottone dell’acqua; tornando indietro tutto rientra.
Le onde le disegna lo script: una curva che sale e scende ogni 360 unità, lunga abbastanza da scorrere di 720 e ricominciare. I pesci attraversano ognuno con il suo passo, fra i secondi di SWIM, con una piccola rotazione al posto dell’ondeggiare; i raggi oscillano con skewX e le alghe si piegano intorno al piede.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
GROW | script.js | 19 | Quanto cresce la superficie oltre la sua misura: alla fine è 1 + GROW volte più grande, venti con 19. |
BLUR | script.js | 10 | Quanto si sfoca la superficie alla fine, in pixel. |
LENGTH | script.js | 2.2 | Quanto dura il tuffo, in altezze di finestra di scorrimento. |
SCRUB | script.js | 0.6 | I secondi che il tuffo impiega a raggiungere lo scorrimento. |
FADE | script.js | [0.82, 1] | Fra questi due punti del tuffo la superficie sfuma via. |
SWIM | script.js | [14, 26] | Il pesce più lento e il più veloce, in secondi per attraversare lo schermo. |
WAVE | script.js | 9 | I secondi che un’onda impiega a scorrere di una lunghezza. |
Per entrare in un mondo: un’immersione, un viaggio, un museo, un gioco, un prodotto in cui si guarda dentro. Serve una forma che si riconosce anche piccola, come una maschera, un oblò, il buco di una serratura o un marchio pieno, e una seconda scena che valga la pena di vedere intera.
Il disegno copre lo schermo stretto tagliando i lati, quindi la maschera resta grande, circa metà della larghezza. Il dito fa il tuffo come la rotella, con la stessa sfocatura.
La superficie non cresce e non si sfoca: scorrendo sfuma nell’acqua fra un quarto e tre quinti del tuffo. Onde, pesci, raggi e alghe stanno fermi, con i pesci in fila nell’acqua.
GSAP 3.15.0, Space Grotesk (font variabile) 5.3.0, Instrument Serif 5.3.0.
Compressi con gzip, i tre file della demo pesano 6,2 KB; le librerie: GSAP + ScrollTrigger 45 KB.
Provata il 2 ottobre 2026
Puoi usarla nei tuoi progetti e in quelli dei tuoi clienti. Non puoi rivenderla né ridistribuirla così com’è. GSAP resta sotto la sua licenza Standard. Licenza completa.
Con l’email e la password del tuo account.
oppure con l’email
Hai fatto l’accesso come .
Con l’account scarichi lo zip di ogni animazione e di ogni pacchetto, gratis.