Vai al contenuto
animorio
EN
Torna alla libreria

Le foto fra le parole

Testo, ImmaginiGSAP, Solo CSSFacilePeso compresso: Demo 4,6 KBGSAP + CustomEase 31 KBGratisScarica lo zip

Una frase grande con piccole immagini infilate dopo alcune parole. Alcune sono aperte, una alla volta si chiudono e altre si aprono altrove: le parole dopo scivolano indietro a chiudere il buco o si fanno da parte, e le righe cambiano forma di continuo.

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>Pictures between the words</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/dm-sans@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header class="bar">
    <a class="brand" href="#">Slip &amp; Fire</a>
    <nav class="bar__nav" aria-label="Sections">
      <a href="#">Shop</a>
      <a href="#">Classes</a>
      <a href="#">Visit</a>
    </nav>
  </header>

  <main class="stage">
    <!-- the sentence: each picture is a small window that follows its word; the script opens and closes them in turn.
         A word, its window and the punctuation after it stay together on one line -->
    <h1 class="sentence" data-sentence>
      Every <span class="pair">cup<span class="win" data-win><svg class="win__pic" viewBox="0 0 138 100" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
        <rect width="138" height="100" fill="#c9643f"/>
        <ellipse cx="69" cy="80" rx="40" ry="8" fill="#a54f30"/>
        <path d="M44 34h46l-4 38c-1 6-6 10-12 10H60c-6 0-11-4-12-10z" fill="#f3e7d3"/>
        <path d="M44 34h46l-1 8H45z" fill="#e3d2b8"/>
        <path d="M89 44c11 0 15 6 14 12s-7 11-17 11" fill="none" stroke="#f3e7d3" stroke-width="6" stroke-linecap="round"/>
        <path d="M60 25c-4-5 4-8 0-14M72 25c-4-5 4-8 0-14" fill="none" stroke="#f3e7d3" stroke-width="3" stroke-linecap="round" opacity="0.75"/>
      </svg></span></span> starts as river <span class="pair">clay<span class="win" data-win><svg class="win__pic" viewBox="0 0 138 100" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
        <rect width="138" height="100" fill="#dbc6a6"/>
        <ellipse cx="69" cy="82" rx="46" ry="7" fill="#c4ab87"/>
        <path d="M31 78c-4-16 6-34 24-40 9-3 13-14 25-12 14 2 18 14 24 22 8 10 7 24 3 30z" fill="#9a6a4d"/>
        <path d="M45 66c4-10 14-16 24-16s18 6 21 14" fill="none" stroke="#b9876a" stroke-width="3" stroke-linecap="round"/>
        <path d="M52 70c3-7 10-11 17-11s13 4 15 10" fill="none" stroke="#b9876a" stroke-width="3" stroke-linecap="round"/>
        <path d="M60 31c5-4 12-5 17-2" fill="none" stroke="#c8987b" stroke-width="4" stroke-linecap="round"/>
      </svg></span>,</span> takes its colour from wood <span class="pair">ash<span class="win" data-win><svg class="win__pic" viewBox="0 0 138 100" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
        <rect width="138" height="100" fill="#7b8a5c"/>
        <ellipse cx="69" cy="80" rx="38" ry="7" fill="#64724a"/>
        <path d="M33 38h72c-2 22-15 40-36 40S35 60 33 38z" fill="#2f3a33"/>
        <path d="M33 38h72c0 7-1 13-3 18-3-4-6 0-8 7-2-5-5-6-7 1-3-6-7-6-9 3-2-7-6-8-9-1-3-6-7-5-9 2-3-6-6-5-9-1-4-7-7-5-9-1-2-6-3-12-3-18z" fill="#bcd3b4"/>
        <ellipse cx="69" cy="38" rx="36" ry="7" fill="#d7e6cf"/>
        <ellipse cx="69" cy="38" rx="28" ry="4.6" fill="#a9c29f"/>
      </svg></span></span> and spends a night in the <span class="pair">kiln<span class="win" data-win><svg class="win__pic" viewBox="0 0 138 100" preserveAspectRatio="xMidYMid slice" aria-hidden="true">
        <rect width="138" height="100" fill="#23324a"/>
        <path d="M30 88V52c0-22 17-38 39-38s39 16 39 38v36z" fill="#8a4b3a"/>
        <path d="M42 88V56c0-15 12-27 27-27s27 12 27 27v32z" fill="#140f12"/>
        <path d="M50 88c-6-12 4-18 4-28 6 6 6 12 6 12 2-10 8-16 8-24 7 9 12 16 10 26 3-4 5-8 4-13 7 9 9 18 5 27z" fill="#f08a3c"/>
        <path d="M58 88c-3-8 3-12 4-18 3 4 4 7 3 9 3-6 6-10 6-15 5 7 8 13 5 24z" fill="#ffd166"/>
      </svg></span>.</span>
    </h1>
    <p class="note">Thrown, glazed and fired by four people in one small workshop.</p>
  </main>

  <footer class="foot">
    <button class="foot__pause" type="button" data-pause aria-pressed="false">Pause the pictures</button>
  </footer>

  <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/CustomEase.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.

26 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 «Le foto fra le parole» da Animorio e adattala al mio sito

Cosa fa

La home di un laboratorio di ceramica inventato, Slip & Fire. Al centro, in un serif morbido, la frase «Every cup starts as river clay, takes its colour from wood ash and spends a night in the kiln.»: dopo «cup», «clay», «ash» e «kiln» c’è una piccola immagine disegnata, una tazza su terracotta, una zolla d’argilla, una ciotola con lo smalto colato, il forno acceso. La frase entra salendo, ancora senza immagini, poi le prime tre si aprono una dopo l’altra e spingono le parole. Da lì ogni secondo e mezzo una finestra si chiude, il testo dopo scivola indietro, e mezzo secondo più tardi si apre quella che era chiusa: le righe vanno a capo in punti diversi e la frase non è mai uguale. Le finestre fanno a turno, la più vecchia si chiude per prima, e dopo quattro cambi tutto torna com’era. Mentre una finestra si chiude l’immagine dentro resta grande e si ingrandisce appena, come una porta che si accosta. In basso un bottone ferma e riavvia le immagini.

Come funziona

Una finestra nel testo

Ogni immagine sta in uno span inline-block con overflow: hidden e gli angoli arrotondati, attaccato alla sua parola senza spazio; lo spazio viene dopo, nel testo. La parola, la sua finestra e la punteggiatura che segue stanno in uno span con white-space: nowrap, così non vanno mai a capo separate. La finestra si apre e si chiude cambiando insieme la larghezza e il margine sinistro: chiusa, fra la parola e la successiva resta uno spazio solo.

L’immagine che non si schiaccia

Dentro la finestra l’SVG ha sempre la larghezza piena (WIDTH em) ed è centrato con left: 50% e un margine negativo pari a metà: la finestra lo ritaglia, non lo deforma. Mentre si chiude l’immagine cresce fino a SINK, mentre si apre torna a 1.

In em, sempre

Larghezze e margini vanno e vengono in em, scritti da tutti e due i lati del tween: se cambia la grandezza del carattere (girando il telefono, per esempio) le finestre aperte restano giuste anche nei giri successivi del ciclo, che altrimenti ricorderebbero i pixel della prima volta.

I turni

All’inizio sono aperte le prime OPEN finestre. Il ciclo si calcola una volta: a ogni cambio si chiude la finestra aperta da più tempo e si apre quella chiusa da più tempo. Con quattro finestre dopo quattro cambi si torna alla partenza, quindi la timeline può ripetersi all’infinito. I tween del ciclo hanno immediateRender: false: altrimenti, appena creati, aprirebbero subito le finestre che l’entrata deve ancora aprire.

Fermarla

Il bottone in fondo ferma l’entrata e il ciclo, e li fa ripartire da dove erano; dice la sua scelta con aria-pressed. Un testo che si muove da solo per più di cinque secondi deve potersi fermare.

Valori da cambiare

NomeFileDi partenzaCosa cambia
OPENscript.js3Quante immagini sono aperte nello stesso momento; ne resta sempre almeno una chiusa.
HOLDscript.js1.5I secondi fra un cambio e il successivo.
SWAPscript.js0.5I secondi che un’immagine impiega a chiudersi, e la successiva ad aprirsi.
WIDTHscript.js1.38La larghezza di una finestra aperta, in altezze di lettera.
GAPscript.js0.18Lo spazio fra una parola e la sua immagine, in altezze di lettera.
SINKscript.js1.18Quanto cresce l’immagine dentro la finestra mentre si chiude.
DELAYscript.js0.5I secondi prima che si apra la prima immagine.
--radiusstyle.css0.16emGli angoli delle finestre, in altezze di lettera.
--claystyle.css#f4ece0Il colore della pagina.

Provali nel Playground

Quando usarla

Per una frase d’apertura che dice di cosa è fatto qualcosa: ingredienti, materiali, persone, luoghi. Vuole immagini piccole e leggibili anche a un centimetro, quindi soggetti semplici su fondi pieni; con foto affollate diventano macchie. Rende meglio centrata e su tre o quattro righe, dove gli a capo che cambiano si vedono.

Sul telefono

La frase scende a 28-40 pixel e va su cinque righe; le finestre seguono la grandezza del carattere perché sono in em. Il ciclo è lo stesso.

Con il movimento ridotto

Niente entrata e niente ciclo: le prime tre immagini sono aperte e restano così, e il bottone per fermarle non serve e non c’è.

Trappole

  • Un fromTo dentro una timeline disegna subito il suo inizio, anche se la timeline è ferma: i tween del ciclo che chiudono le finestre, appena creati, le aprirebbero tutte prima dell’entrata. Nel ciclo vogliono immediateRender: false.
  • Uno spazio prima e uno dopo la finestra, nell’HTML, lasciano due spazi quando è chiusa: lo spazio prima è il margine sinistro della finestra, che si chiude con lei.
  • Dopo un elemento inline-block il browser può andare a capo anche senza spazio: senza nowrap una virgola dopo l’immagine finiva da sola all’inizio della riga dopo. La virgola sta dentro lo span della parola.
  • In Safari un riquadro con gli angoli arrotondati e overflow: hidden non sempre ritaglia un figlio trasformato: la finestra ha un suo livello (translateZ(0)).

Librerie

GSAP 3.15.0, CustomEase (GSAP) 3.15.0, Fraunces (font variabile) 5.3.0, DM Sans (font variabile) 5.3.0.

Compressi con gzip, i tre file della demo pesano 4,6 KB; le librerie: GSAP + CustomEase 31 KB.

Collaudo

Provata il 1 ottobre 2026

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

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