Vai al contenuto
animorio
EN
Torna alla libreria

La transizione delle parole che restano

Transizioni, TestoGSAP, Solo CSSMediaPeso compresso: Demo 8,8 KBGSAP 28 KBGratisScarica lo zip

Un cambio di pagina nello stile minimal: le parole che le due pagine hanno in comune non se ne vanno mai. Al clic le altre svaniscono a onda, e quelle che restano volano una dopo l’altra al loro posto nella pagina nuova, crescendo o rimpicciolendo e cambiando peso; si posano su una riga sottile, prendono un filo di peso dal colpo e lo restituiscono, poi salgono le parole nuove e per ultimo cade il punto rosso.

Il codice

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 words-that-stay transition</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage" data-stage>
    <!-- the header is the same on both pages, so it never moves -->
    <header class="bar">
      <span class="brand">Quarra</span>
      <nav class="nav" aria-label="Pages">
        <a href="#index" data-go="a" data-nav="a" aria-current="page">Index</a>
        <a href="#rooms" data-go="b" data-nav="b">Rooms</a>
      </nav>
    </header>

    <!-- the first page. The words marked with the same data-share on both pages are the ones that stay:
         they fly to their place on the other page, changing size and weight -->
    <section class="page page--a is-on" data-page="a" aria-label="Index">
      <div class="col col--a">
        <h1 class="headline" data-words><span data-share="quiet">Quiet</span> <span data-share="rooms">rooms</span><br>for loud cities<span class="dot" data-share="dot">.</span></h1>
        <p class="lede" data-words>An architecture studio in <span data-share="porto">Porto</span>: <span data-share="twelve">twelve</span> <span data-share="houses">houses</span>, one school, no towers.</p>
        <a class="go go--next" href="#rooms" data-go="b" data-autoclic data-unit>
          <span class="go__text">See the rooms</span>
          <span class="go__arrow" aria-hidden="true"><span class="go__shaft"></span><svg class="go__head" viewBox="0 0 8 12"><path d="M1.5 1.5 6.5 6l-5 4.5"/></svg></span>
        </a>
      </div>
    </section>

    <!-- the second page -->
    <section class="page page--b" data-page="b" aria-label="Rooms" aria-hidden="true">
      <div class="col col--b">
        <p class="sub" data-words><span data-share="quiet">Quiet</span> <span data-share="houses">houses</span>, <span data-share="twelve">twelve</span> of them.</p>
        <p class="lede" data-words>Each one built in <span data-share="porto">Porto</span> around a single window, and a room left empty on purpose.</p>
        <a class="go go--back" href="#index" data-go="a" data-autoclic data-unit>
          <span class="go__arrow" aria-hidden="true"><svg class="go__head" viewBox="0 0 8 12"><path d="M6.5 1.5 1.5 6l5 4.5"/></svg><span class="go__shaft"></span></span>
          <span class="go__text">Back to the index</span>
        </a>
      </div>
      <h2 class="title" data-words><span data-share="rooms">rooms</span><span class="dot" data-share="dot">.</span></h2>
    </section>

    <footer class="foot">
      <span>Since 2009</span>
      <span>Visits by appointment</span>
    </footer>

    <!-- the words in flight and the baselines they land on (built and moved by the script) -->
    <div class="fly" data-fly aria-hidden="true"></div>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

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.

39 valori da cambiare

Oppure chiedila a Claude Code

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 transizione delle parole che restano» da Animorio e adattala al mio sito

Cosa fa

Il sito di uno studio di architettura inventato, Quarra, in due pagine e quasi niente: fondo color carta, inchiostro quasi nero e un solo punto rosso. Nella prima pagina il titolo, sottilissimo, dice Quiet rooms for loud cities., sotto c’è una riga piccola sullo studio e il link See the rooms. All’apertura due righe sottili si disegnano dove poggeranno le lettere, le parole salgono una dopo l’altra, il punto cade dall’alto, si schiaccia sulla riga e torna tondo. Al clic le parole che la pagina nuova non usa svaniscono a onda, a partire dal link; quelle che servono anche dopo (Quiet, rooms, twelve, houses, Porto e il punto) si sollevano di un pelo e partono una dopo l’altra, ognuna con la sua curva. Mentre volano cambiano grandezza e peso: Quiet passa dal titolo sottile a una riga media e decisa, twelve e houses dalla riga piccola e grigia a quella grande e nera, rooms diventa il titolo enorme e nerissimo in fondo alla pagina. In volo si stringono un po’, come chi corre, e quando arrivano si allargano di nuovo. Sotto di loro si disegnano le righe di base della pagina nuova; ogni parola ci si posa con un piccolo schiacciamento, prende un filo di peso in più dal colpo e lo restituisce con una molla, e la riga sente il colpo. Poi le parole nuove salgono al loro posto, le righe si ritirano e per ultimo il punto rosso, grande come una lettera del titolo, cade accanto a rooms. Back to the index fa lo stesso viaggio al contrario.

Come funziona

Le parole in comune

Nell’HTML le parole che restano sono segnate con lo stesso data-share sulle due pagine (data-share="rooms" nel titolo della prima e nel titolo della seconda). Lo script divide in parole tutto quello che ha data-words: ogni parola diventa uno span inline-block, così si muove senza spostare le vicine, mentre gli spazi restano testo e le righe vanno a capo come prima. Le parole senza gemella sono quelle che se ne vanno o che arrivano.

Tutto quello che serve per ridisegnarle

Al clic, per ogni coppia lo script legge la parola di partenza e quella d’arrivo: la x, la linea di base (con un elemento vuoto alto zero messo dentro la parola), la grandezza, il peso, la larghezza (font-stretch), la spaziatura in em e il colore. Le due pagine sono sempre impaginate, anche quella nascosta con visibility: hidden, quindi si misurano tutte e due prima che si muova niente.

Il volo

Al posto della parola vera vola una copia in un livello sopra le pagine, con line-height 1: così la sua linea di base sta sempre a una frazione fissa della grandezza (si misura una volta). Una tween porta t da 0 a 1 e a ogni fotogramma la copia ricalcola tutto: x con power4.inOut, y con expo.inOut (le due curve diverse piegano la strada) più un arco verso l’alto, grandezza, peso, spaziatura e colore con power3.inOut, e la larghezza che scende di SQUEEZE a metà strada con un seno. Roboto Flex ha l’asse ottico, quindi la parola che cresce cambia anche disegno.

L’atterraggio

Un attimo prima di arrivare la copia si schiaccia sulla linea di base (scale con l’origine proprio sulla base), scende di un pixel e prende LANDING di peso in più in 0,08 secondi; poi elastic.out(1, 0.42) le restituisce forma e peso, con l’overshoot di un pixel. La riga sotto fa lo stesso salto di un pixel e torna con la molla. Finito l’assestamento la parola vera compare e la copia sparisce: hanno la stessa grandezza, lo stesso peso e lo stesso posto, quindi non si vede il cambio.

Regia, telefono e movimento ridotto

Ogni cambio è una timeline sola: l’onda delle parole che se ne vanno (stagger calcolato con la distanza dal clic), i voli sfalsati di STAGGER nell’ordine di lettura della pagina nuova, le righe di base, le parole nuove che salgono quando i viaggiatori sono quasi arrivati e il punto per ultimo; SPEED è il timeScale. Un clic che arriva mentre la pagina cambia aspetta in coda. I due titoli grandi si adattano alla larghezza e all’altezza dello schermo e si rimpiccioliscono se toccherebbero il resto. Con il movimento ridotto le parole che restano non volano: la pagina vecchia svanisce e la nuova compare in dissolvenza, già composta.

Valori da cambiare

NomeFileDi partenzaCosa cambia
FLYscript.js1.1I secondi che ogni parola impiega a volare al suo posto nuovo.
STAGGERscript.js0.08I secondi fra la partenza di una parola e quella dopo: 0 = partono tutte insieme.
ARCscript.js0.16Quanto il volo si piega verso l’alto, rispetto alla strada da fare: 0 = in linea retta.
SQUEEZEscript.js24Quanto una parola si stringe mentre vola (sull’asse della larghezza): 0 = resta larga uguale.
LANDINGscript.js90Il peso in più che una parola prende quando si posa, e poi restituisce: 0 = nessun colpo.
GUIDESscript.jstrueLe righe di base della pagina nuova che si disegnano sotto le parole che arrivano.
SPEEDscript.js1La velocità di tutto: 2 è il doppio, 0.5 la metà.

Provali nel Playground

Quando usarla

Per passare da una pagina all’altra in un sito sobrio dove le parole contano: uno studio di architettura o di design, un portfolio, una rivista, la home che porta a una sezione o a un progetto, l’elenco che porta alla scheda. Funziona meglio quando le due pagine hanno davvero qualche parola in comune: il nome di una sezione, il titolo di un progetto, una parola chiave che passa da piccola a grande.

Sul telefono

La stessa transizione con le misure adattate: il titolo della prima pagina e quello della seconda si adattano alla larghezza dello schermo, il testo va a capo e le parole volano lo stesso fra le due impaginazioni, con le stesse curve e gli stessi atterraggi. Un tocco sul link la fa partire.

Con il movimento ridotto

Niente si sposta: la prima pagina svanisce, le parole che restano compaiono già al loro posto nella seconda e poi le altre, in dissolvenza; al ritorno lo stesso al contrario. L’entrata è una dissolvenza.

Trappole

  • Una parola che cambia grandezza dentro una riga di testo, allargandosi, spingerebbe tutte le vicine. Per questo vola una copia in un livello a parte, posizionata con transform, e la parola vera resta trasparente al suo posto.
  • Il riquadro di una parola (getBoundingClientRect) dipende dall’interlinea e dal carattere, quindi non serve per allineare due grandezze diverse: si usa la linea di base, misurata con un elemento vuoto alto zero allineato alla base dentro la parola.
  • Le righe di base dell’entrata venivano misurate dopo aver abbassato le parole di 18 pixel per farle salire: le righe stavano sotto le lettere. Si misurano prima di spostare qualsiasi cosa.
  • Il punto grande arrivava mentre rooms era ancora gonfio del peso dell’atterraggio, e per un attimo si posava sopra la s: parte dopo, quando rooms ha restituito il peso. Nel titolo ha anche un piccolo margine a sinistra, perché la spaziatura stretta lo attaccava alla lettera.
  • Le righe di base sotto il testo piccolo erano troppo vicine fra loro e sembravano una sottolineatura: ci sono solo sotto le righe grandi.
  • Il pilota delle anteprime clicca ogni 2,8 secondi e un cambio dura circa tre secondi: un clic che arriva a metà va in coda e parte appena la timeline finisce.

Librerie

GSAP 3.15.0, Roboto Flex (font variabile) 5.3.0.

Compressi con gzip, i tre file della demo pesano 8,8 KB; le librerie: GSAP 28 KB.

Collaudo

Provata il 15 ottobre 2026

  • Computer: Fatto
  • Telefono: Fatto
  • Movimento ridotto: Fatto
  • Safari su iPhone: Da fare

Licenza d’uso

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.

Tutte le animazioni