Vai al contenuto
animorio
EN
Tutti i componenti

L’indirizzo che diventa etichetta

Moduli, Transizioni, SVGGSAP, Solo CSSImpegnativaPeso compresso: Demo 12 KBGSAP 28 KBGratisScarica lo zip

L’indirizzo di consegna nel checkout di un negozio: nome, via, città, codice postale controllato sulla forma del paese scelto, e paese. Con tutto a posto la scheda stessa diventa l’etichetta di spedizione: i bordi dei campi svaniscono, la scheda si stringe e prende le righe nere di un’etichetta, le parole volano dai campi alle loro righe cambiando misura e peso, il percorso si batte nel riquadro nero e una testina di stampa passa sull’etichetta e stampa un vero codice a barre Code 128.

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 address that becomes a label</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist-mono@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the delivery address of a checkout: with every field right, the card turns into the shipping label, the words
         fly from the fields to their lines and a real Code 128 barcode is printed under them. Sending is pretended:
         see post() in the script -->
    <div class="ship" data-ship data-autoclic>
      <div class="sheet" data-sheet>
        <form class="addr" action="#" novalidate aria-labelledby="ship-title" data-form>
          <h2 class="addr__title" id="ship-title">Delivery address</h2>

          <div class="field" data-field="name">
            <label class="field__label" for="ship-name">Full name</label>
            <div class="field__box" data-box>
              <input class="field__input" id="ship-name" name="name" type="text" autocomplete="shipping name" autocapitalize="words" spellcheck="false" enterkeyhint="next" maxlength="40" aria-describedby="ship-name-err" aria-invalid="false" data-input>
              <span class="field__caret" aria-hidden="true" data-caret></span>
            </div>
            <p class="field__err" id="ship-name-err" data-err></p>
          </div>

          <div class="field" data-field="street">
            <label class="field__label" for="ship-street">Street and number</label>
            <div class="field__box" data-box>
              <input class="field__input" id="ship-street" name="street" type="text" autocomplete="shipping address-line1" spellcheck="false" enterkeyhint="next" maxlength="48" aria-describedby="ship-street-err" aria-invalid="false" data-input>
              <span class="field__caret" aria-hidden="true" data-caret></span>
            </div>
            <p class="field__err" id="ship-street-err" data-err></p>
          </div>

          <div class="addr__row">
            <div class="field" data-field="city">
              <label class="field__label" for="ship-city">Town or city</label>
              <div class="field__box" data-box>
                <input class="field__input" id="ship-city" name="city" type="text" autocomplete="shipping address-level2" spellcheck="false" enterkeyhint="next" maxlength="32" aria-describedby="ship-city-err" aria-invalid="false" data-input>
                <span class="field__caret" aria-hidden="true" data-caret></span>
              </div>
              <p class="field__err" id="ship-city-err" data-err></p>
            </div>
            <div class="field field--post" data-field="post">
              <label class="field__label" for="ship-post">Postcode</label>
              <div class="field__box" data-box>
                <input class="field__input" id="ship-post" name="post" type="text" autocomplete="shipping postal-code" autocapitalize="characters" autocorrect="off" spellcheck="false" enterkeyhint="next" maxlength="10" aria-describedby="ship-post-err" aria-invalid="false" data-input>
                <span class="field__caret" aria-hidden="true" data-caret></span>
              </div>
              <p class="field__err" id="ship-post-err" data-err></p>
            </div>
          </div>

          <div class="field field--country" data-field="country">
            <label class="field__label" for="ship-country">Country</label>
            <div class="field__box" data-box>
              <select class="field__input field__select" id="ship-country" name="country" autocomplete="shipping country" data-country>
                <option value="GB">United Kingdom</option>
                <option value="IE">Ireland</option>
                <option value="IT">Italy</option>
                <option value="DE">Germany</option>
                <option value="FR">France</option>
                <option value="US">United States</option>
              </select>
              <svg class="field__chev" viewBox="0 0 12 12" aria-hidden="true"><path d="M2.5 4.5 6 8l3.5-3.5"/></svg>
            </div>
          </div>

          <div class="addr__foot">
            <button class="send" type="submit" data-send>
              <span class="send__bg" aria-hidden="true"></span>
              <span class="send__label">Ship here</span>
            </button>
          </div>
        </form>

        <!-- the label the card turns into: drawn for the eye, the form above stays the real thing -->
        <div class="label" aria-hidden="true" data-label>
          <div class="label__from">
            <span class="label__cap">From</span>
            <span>Larkspur Goods · Unit 4, Mill Lane · Bristol</span>
          </div>
          <div class="label__main">
            <div class="label__to">
              <span class="label__cap">Ship to</span>
              <span class="label__line label__line--name" data-to="name"></span>
              <span class="label__line" data-to="street"></span>
              <span class="label__line label__line--city"><span data-to="city"></span> <span data-to="post"></span></span>
              <span class="label__line label__line--country" data-to="country"></span>
            </div>
            <div class="label__sort" data-sort>
              <span class="label__cap label__cap--inv">Route</span>
              <span class="label__route" data-route></span>
            </div>
          </div>
          <div class="label__code">
            <svg class="label__bars" data-bars preserveAspectRatio="none"></svg>
            <span class="label__head" data-head></span>
            <span class="label__track" data-track></span>
          </div>
        </div>
      </div>

      <div class="ship__after" data-after>
        <p class="after__line"><span data-after-text>Arrives Thursday, tracked all the way.</span> <button class="after__change" type="button" data-change>Change</button></p>
      </div>
      <p class="sr" role="status" aria-live="polite" data-live></p>
    </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.

33 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 «L’indirizzo che diventa etichetta» da Animorio e adattala al mio sito

Cosa fa

Su una pagina bianca una scheda bianca dagli angoli tondi, Delivery address, con i campi Full name, Street and number, Town or city e Postcode affiancati, e Country con United Kingdom; sotto la pillola nera Ship here. Il campo in uso prende un bordo nero; nel codice postale vuoto si legge in grigio l’esempio del paese scelto (SW1A 2HQ, 20121) e quello che scrivi diventa maiuscolo, e lasciandolo prende lo spazio giusto. Un campo lasciato con qualcosa di sbagliato, o premendo il pulsante, prende un bordo arancione, fa un piccolo scatto di lato e sotto si apre la riga che dice cosa va (UK postcodes look like SW1A 2HQ.); appena è giusto la riga si richiude. Con tutto a posto il pulsante dice Printing the label, i nomi e i bordi dei campi svaniscono lasciando sospese solo le parole scritte, la scheda si stringe all’altezza di un’etichetta con gli angoli quasi vivi, un bordo nero e un’ombra; compaiono le righe nere, From Larkspur Goods in alto, Ship to e il riquadro nero Route. Le parole volano una dopo l’altra dai campi alle righe dell’etichetta, il nome più grande e più pesante, città, codice e paese in maiuscolo; nel riquadro si batte SW1A 2HQ; poi una sottile riga arancione corre sotto da sinistra a destra e dietro di lei si stampa il codice a barre, mentre sotto si batte il numero di tracciamento, LG 182 626 096 GB. Sotto l’etichetta si apre Arrives Thursday, tracked all the way. e Change: le parole tornano in volo nei loro campi e la scheda si riapre.

Come funziona

Campi veri e il codice postale di ogni paese

Ogni campo ha la sua label, autocomplete di spedizione, aria-invalid e aria-describedby alla riga sotto. Il codice postale si controlla con la forma del paese scelto (Regno Unito, Irlanda, Italia, Germania, Francia, Stati Uniti), diventa maiuscolo mentre scrivi senza spostare il cursore e prende lo spazio giusto quando lo lasci. La riga dell’errore ha un’altezza sua che si apre e si chiude con un tween, quindi i campi sotto scendono e risalgono morbidi.

Le parole in volo (FLIP)

All’invio, su ogni campo si posa una copia delle sue parole nello stesso carattere e nella stessa posizione, e le parole vere diventano trasparenti. Le righe dell’etichetta, già riempite ma invisibili, danno la meta: x, il centro della riga, la misura e il peso. Ogni copia vola con x, y, scale e fontWeight su un’unica timeline, sfalsata di STAGGER; a metà volo le righe in maiuscolo prendono le maiuscole, e all’arrivo la copia lascia il posto alla riga vera.

La scheda che diventa etichetta

Nello stesso momento i nomi e i bordi dei campi svaniscono, l’altezza della scheda va da quella del modulo a quella dell’etichetta, gli angoli da 20 a 6 pixel, il bordo dal grigio al nero con un’ombra: la scheda non viene sostituita, cambia mestiere. Il ritorno fa il volo al contrario, partendo dalla riga più bassa, così le parole che scendono non incrociano quelle che aspettano sopra.

Un vero Code 128

Il numero di tracciamento nasce dall’indirizzo (un hash FNV delle righe, nove cifre, fra le due lettere del mittente e il paese). Il codice a barre è Code 128 set B: l’inizio, ogni carattere con le sue sei larghezze di barra e spazio, il carattere di controllo (somma pesata modulo 103) e la fine, con dieci moduli di silenzio ai lati. Le barre sono rettangoli SVG su una viewBox in moduli, larghe un numero intero di pixel (MODULE) e con shape-rendering crispEdges, quindi si leggono.

La testina di stampa

La stampa è un oggetto da 0 a 1 portato da GSAP in PRINT secondi, senza ease: a ogni passo il clip-path del codice a barre si apre da sinistra fino a quel punto e la riga arancione della testina sta lì, mentre il numero si batte carattere per carattere al ritmo della testina. Nel riquadro Route si battono l’inizio e la fine del codice postale.

Valori da cambiare

NomeFileDi partenzaCosa cambia
FLIGHTscript.js0.8I secondi che le parole impiegano a volare dai campi all’etichetta.
STAGGERscript.js0.07I secondi fra la partenza di una parola e quella dopo.
PRINTscript.js0.9I secondi che la testina impiega ad attraversare il codice a barre.
MODULEscript.js2La larghezza della barra più sottile, in pixel (scende se l’etichetta è stretta).
SENDERscript.jsLGLe due lettere con cui comincia il numero di tracciamento.
WAITscript.js0.5Quanti secondi dura il salvataggio finto dell’indirizzo.

Provali nel Playground

Quando usarla

Nel passo della consegna di un checkout, in un negozio che spedisce: l’etichetta dice a chi compra, meglio di un riepilogo, che l’indirizzo è giusto e dove andrà il pacco. Va bene anche nella pagina degli indirizzi di un account o in un’app di spedizioni.

Sul telefono

La scheda prende la larghezza dello schermo (358 pixel su un telefono di 390), città e codice postale restano affiancati, i campi sono alti 46 pixel e i caratteri 16, quindi Safari non ingrandisce. Il codice postale apre la tastiera con le maiuscole, Country apre il selettore del telefono. Sull’etichetta il riquadro del percorso si stringe e il codice a barre resta a moduli interi, centrato.

Con il movimento ridotto

Niente voli, niente scatti e niente testina: le righe degli errori compaiono in dissolvenza, e all’invio il modulo svanisce e l’etichetta compare già stampata, col codice a barre e il numero interi. Change fa lo stesso al contrario.

Trappole

  • Nella riga di città e codice postale il secondo campo prendeva il margine di un campo che segue un altro campo e scendeva di 14 pixel rispetto al primo: ora dentro la riga quel margine è zero.
  • Al ritorno le parole partivano tutte insieme da righe a 17 pixel l’una dall’altra e si accavallavano in volo. Ora parte prima la riga più bassa, con più distanza fra una partenza e l’altra: scendono verso campi lontani senza incrociarsi.
  • Un codice a barre stirato su una larghezza qualsiasi ha barre di mezzo pixel che non si leggono. Ora ogni modulo è un numero intero di pixel, al massimo MODULE, e il codice è centrato.

Librerie

GSAP 3.15.0, Geist (font variabile) 5.3.0, Geist Mono (font variabile) 5.3.0.

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

Collaudo

Provata il 19 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.

Tutti i componenti