Vai al contenuto
animorio
EN
Tutti i componenti

La barra con l'insegna

Navigazione, Fisica, HoverSolo CSS, GSAPImpegnativaPeso compresso: Demo 12 KBGSAP 28 KBGratisScarica lo zip

La barra in basso dell'app di un caffè di quartiere: sopra la voce scelta pende una piccola insegna smaltata col suo nome, appesa con due cordini a una barretta d'ottone. Cambiando voce i ganci corrono sulla barretta e l'insegna li segue in ritardo: resta indietro, si inclina, oscilla oltre e si assesta come un corpo rigido vero, poi l'icona sotto fa un salto e le dà un colpetto.

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 shop sign tab bar</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the tab bar of a neighbourhood café's app, on a cream board. Along its top runs a thin brass rail, and from
         two hooks on it hangs a small enamel sign with the name of the tab you are on, like the plate over a shop
         door. Choosing another tab, the hooks run along the rail and the sign follows on its two cords: it trails,
         tilts, swings past and settles, and the icon under it hops. The sign is a rigid plate worked out by the
         script on every frame -->
    <nav class="bar" aria-label="Main" data-bar>
      <button class="tab" type="button" data-tab data-autoclic>
        <span class="tab__lift" data-lift>
          <svg class="tab__icon" viewBox="0 0 24 24" aria-hidden="true">
            <path class="tab__fill" d="M5.4 4.6h13.2l1.6 4.6H3.8z"/>
            <path d="M3.8 9.2 5.4 4.6h13.2l1.6 4.6M8.7 4.6l-.8 4.6M12 4.6v4.6M15.3 4.6l.8 4.6"/>
            <path d="M3.8 9.2a2.05 2.05 0 0 0 4.1 0a2.05 2.05 0 0 0 4.1 0a2.05 2.05 0 0 0 4.1 0a2.05 2.05 0 0 0 4.1 0"/>
            <path d="M5.3 12.4v7.4h13.4v-7.4M10.2 19.8v-4.4h3.6v4.4"/>
          </svg>
        </span>
        <span class="sr" data-name>Home</span>
      </button>
      <button class="tab" type="button" data-tab>
        <span class="tab__lift" data-lift>
          <svg class="tab__icon" viewBox="0 0 24 24" aria-hidden="true">
            <path class="tab__fill" d="M5.2 10.2h11.2v3a5.2 5.2 0 0 1-5.2 5.2h-.8a5.2 5.2 0 0 1-5.2-5.2z"/>
            <path d="M5.2 9.4h11.2v3.8a5.2 5.2 0 0 1-5.2 5.2h-.8a5.2 5.2 0 0 1-5.2-5.2zM16.4 10.6h1.2a2.3 2.3 0 0 1 0 4.6h-1.5M3.8 20.6h14"/>
            <path d="M8.9 3.4c-.9 1.1.9 2.1 0 3.4M12.6 3.4c-.9 1.1.9 2.1 0 3.4" data-steam/>
          </svg>
        </span>
        <span class="sr" data-name>Menu</span>
      </button>
      <button class="tab" type="button" data-tab data-autoclic>
        <span class="tab__lift" data-lift>
          <svg class="tab__icon" viewBox="0 0 24 24" aria-hidden="true">
            <path class="tab__fill" d="M5.6 8.4h12.8l-.9 11.2a1 1 0 0 1-1 .9H7.5a1 1 0 0 1-1-.9z"/>
            <path d="M5.6 8.4h12.8l-.9 11.2a1 1 0 0 1-1 .9H7.5a1 1 0 0 1-1-.9zM9.2 10.8V7.4a2.8 2.8 0 0 1 5.6 0v3.4"/>
          </svg>
        </span>
        <span class="sr" data-name>Orders</span>
      </button>
      <button class="tab" type="button" data-tab>
        <span class="tab__lift" data-lift>
          <svg class="tab__icon" viewBox="0 0 24 24" aria-hidden="true">
            <path class="tab__fill" d="M7 4.4h10a.6.6 0 0 1 .6.6v15.2l-5.6-4-5.6 4V5a.6.6 0 0 1 .6-.6z"/>
            <path d="M7 4.4h10a.6.6 0 0 1 .6.6v15.2l-5.6-4-5.6 4V5a.6.6 0 0 1 .6-.6z"/>
          </svg>
        </span>
        <span class="sr" data-name>Saved</span>
      </button>
      <button class="tab" type="button" data-tab data-autoclic>
        <span class="tab__lift" data-lift>
          <svg class="tab__icon" viewBox="0 0 24 24" aria-hidden="true">
            <path class="tab__fill" d="M12 4.4a3.7 3.7 0 1 0 0 7.4a3.7 3.7 0 1 0 0-7.4z"/>
            <path d="M12 4.4a3.7 3.7 0 1 0 0 7.4a3.7 3.7 0 1 0 0-7.4zM4.8 20.2c.9-3.7 3.7-5.7 7.2-5.7s6.3 2 7.2 5.7"/>
          </svg>
        </span>
        <span class="sr" data-name>Profile</span>
      </button>

      <!-- the brass rail along the top, and everything that hangs from it: the sign's shadow on the board, the two
           cords, the two hooks and the sign. None of it takes the taps -->
      <span class="rail" aria-hidden="true" data-rail></span>
      <span class="hanger" aria-hidden="true" data-hanger>
        <span class="shade" data-shade></span>
        <svg class="cords">
          <g class="cords__shade" transform="translate(1 2.4)"><path data-cord-shade/><path data-cord-shade/></g>
          <g class="cords__line"><path data-cord/><path data-cord/></g>
        </svg>
        <span class="hook" data-hook></span>
        <span class="hook" data-hook></span>
        <span class="sign" data-sign>
          <span class="sign__plate">
            <span class="sign__rule"></span>
            <span class="sign__words" data-words></span>
            <span class="sign__side" data-side></span>
            <span class="sign__gloss" data-gloss></span>
          </span>
          <span class="sign__clip" data-clip></span>
          <span class="sign__clip sign__clip--right" data-clip></span>
        </span>
      </span>
    </nav>
  </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.

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 «La barra con l'insegna» da Animorio e adattala al mio sito

Cosa fa

Su un fondo bianco, da sola al centro, una barra color crema come un'asse dipinta, alta 72 pixel, con cinque icone disegnate a tratto: una bottega con la tenda a festoni, una tazza fumante, un sacchetto di carta, un segnalibro e una persona, cioè Home, Menu, Orders, Saved e Profile. Lungo il bordo alto corre una barretta d'ottone sottile, fissata da due staffe ai lati, e su Menu pende una piccola insegna smaltata color vinaccia, col bordino chiaro dipinto tutt'intorno e il nome MENU in lettere graziate maiuscole, appesa con due cordini scuri a due ganci d'ottone che stringono la barretta. Sotto l'insegna la tazza è scura e piena di un velo del colore dell'insegna; le altre icone sono grigio caldo. All'arrivo la barra sale e l'insegna viene appesa: compare un poco più in alto e storta, coi cordini molli, cade, il cordino più basso si tende per primo e lei dondola fino a fermarsi. Scegliendo un'altra voce, i due ganci corrono sulla barretta, quello davanti qualche pixel in anticipo: i cordini si piegano all'indietro e l'insegna resta indietro inclinandosi, poi, quando i ganci frenano, passa oltre, torna e si assesta. A metà strada il nome cambia lettera per lettera, le vecchie che salgono e spariscono e le nuove che arrivano dal basso, dal lato verso cui va. Appena i ganci si fermano l'icona nuova si scurisce, fa un saltello che la allunga un poco, urta il bordo dell'insegna (che sobbalza, coi cordini che per un attimo si allentano e si piegano) e atterra schiacciandosi. Se l'insegna oscillando scende troppo su un'icona che sta passando, l'icona cede e si piega dal lato premuto. Col mouse sopra un'altra voce, o col dito giù, l'insegna si gira verso di lei in prospettiva: il lato lontano si stringe e si scurisce, il riflesso dello smalto scivola e i ganci si spostano appena verso la voce. Cliccando la voce già scelta l'insegna riceve un buffetto: dondola, gira un poco su se stessa e l'icona sotto le dà un colpetto. Da tastiera il Tab gira l'insegna verso la voce col fuoco, che ha un anello intorno all'icona; le frecce, Inizio e Fine scelgono.

Come funziona

Una lastra rigida di quattro punti

L'insegna sono i suoi quattro angoli, quattro punti con posizione e velocità. Sei vincoli di distanza li tengono rigidi: i quattro lati e le due diagonali. A ogni passo di calcolo i punti si muovono con la loro velocità e la gravità, poi i vincoli rimettono a posto le posizioni (sei giri), e la velocità nuova è lo spostamento vero diviso il tempo: l'integrazione di Verlet scritta con le velocità, che accetta i colpi e le spinte. Passi di al massimo 1/240 di secondo, fotogrammi di al massimo 1/30.

Due cordini che tirano e non spingono

Ogni cordino è un vincolo che agisce solo quando è teso: se il punto a cui è legato è più lontano dal gancio della lunghezza del cordino, la lastra viene tirata indietro. Il punto di legatura sta dentro la lastra, quindi è una miscela di tre angoli, e la correzione si divide fra loro secondo il loro peso nella miscela. I cordini sono un poco inclinati verso l'interno (TOE): con cordini paralleli la lastra scivolerebbe dritta come un'altalena, così invece dondola inclinandosi, come un pendolo appeso a un punto sopra la barretta.

I ganci e lo smorzamento

I ganci li porta GSAP: una tween sposta il loro punto di mezzo con power2.inOut, e un'altra fa correre quello davanti qualche pixel avanti e poi lo riporta. Dentro il fotogramma i ganci si spostano un poco a ogni passo di calcolo, così anche a 30 fotogrammi al secondo la lastra non riceve strappi. Lo smorzamento agisce sulla velocità della lastra rispetto a quella dei ganci: frena l'oscillazione, non il viaggio.

La torsione e il disegno

Girare verso una voce è la torsione di un'insegna appesa a due fili (un pendolo bifilare), con la sua molla: la rigidezza viene dalla gravità, dalla distanza fra i cordini, dalla loro lunghezza e dalla larghezza dell'insegna. L'insegna è un elemento HTML vero (il testo resta nitido) spostato con translate, rotate e perspective più rotateY; i cordini sono due tracciati SVG fino ai fermagli, calcolati con la stessa prospettiva, dritti se tesi e incurvati verso l'esterno se allentati; l'ombra sul fondo segue la lastra.

Le icone che sentono l'insegna

Quando l'insegna arriva, l'icona sotto salta con una timeline di GSAP; mentre sale diventa un ostacolo che il risolutore conosce: se il bordo basso della lastra le sta dentro, viene spinto su, e la lastra sobbalza da sola. Al contrario, se la lastra oscillando scende su un'icona, l'icona viene spinta giù e piegata dal lato premuto, e torna su una molla. Le voci sono button in un nav, quella scelta ha aria-current="page"; quando niente si muove più il ciclo smette di calcolare e di disegnare.

Valori da cambiare

NomeFileDi partenzaCosa cambia
STARTscript.js1La voce scelta all'apertura della pagina (0 è la prima).
TRAVELscript.js0.46I secondi che i ganci ci mettono ad arrivare alla voce accanto (a una lontana un po' di più).
LEADscript.js5Di quanti pixel il gancio davanti corre avanti a quello dietro durante il viaggio: l'insegna si inclina.
CORDscript.js7La lunghezza dei due cordini, in pixel.
TOEscript.js3.5Quanto i cordini si inclinano l'uno verso l'altro, in pixel: di più, l'insegna dondola inclinandosi di più (0, scivola dritta).
GRAVITYscript.js2400Quanto pesa l'insegna, in pixel al secondo quadrato: di più, oscillazioni più rapide e più piccole.
DAMPINGscript.js2.6Quanto presto si spegne l'oscillazione: di più, si ferma prima.
TURNscript.js30Di quanti gradi l'insegna si gira verso la voce sotto il mouse o sotto il dito.
HOPscript.js6Quanto salta l'icona quando l'insegna le arriva sopra, in pixel (sopra i 5 circa le dà un colpetto).

Provali nel Playground

Quando usarla

Per la barra in basso di un'app pensata per il telefono, con quattro o cinque sezioni, quando l'app ha un carattere di bottega: un caffè, una libreria, un forno, un negozio di quartiere, un'app di ricette. L'insegna dice dove si è anche da ferma, al posto delle etichette sotto le icone.

Sul telefono

La barra è larga al massimo 420 pixel e sul telefono si stringe allo schermo con 16 pixel di margine per lato (358 su un telefono di 390); resta alta 72 e ogni voce è un bersaglio di circa 69 per 72 pixel. L'insegna è larga 60 pixel e sta dentro la sua colonna anche lì. Col dito giù su una voce l'insegna si gira verso di lei, come col mouse sopra, e il tocco la sceglie. In verticale la pagina scorre ancora (touch-action: pan-y).

Con il movimento ridotto

Niente viaggio, niente oscillazione, niente torsione e niente salto: l'insegna, coi suoi cordini e i ganci, sparisce in dissolvenza dalla voce vecchia e ricompare ferma e dritta sulla nuova, col nome nuovo, mentre le icone si accendono e si spengono in dissolvenza. All'arrivo la barra compare solo in dissolvenza, con l'insegna già appesa.

Trappole

  • Il gancio dietro all'inizio partiva in ritardo di un tempo fisso: alle velocità del viaggio i ganci si allontanavano più dei fermagli dell'insegna, i due cordini tiravano verso l'esterno e la lastra veniva sollevata contro la barretta, coi cordini quasi orizzontali. Ora il gancio davanti corre avanti di pochi pixel al massimo (LEAD) e poi rientra.
  • Girando verso una voce, la prospettiva avvicina i fermagli visti sullo schermo: i cordini risultavano più lunghi della distanza, venivano disegnati allentati e si arricciavano come uncini. Se un cordino è allentato lo decide la lastra vera; la torsione sposta solo il punto in cui il cordino si disegna.
  • Tornando indietro a metà viaggio, l'anticipo passava da un gancio all'altro e i ganci saltavano. Ora, quando la direzione cambia, il punto di mezzo del viaggio si sposta della stessa quantità: gli stessi due ganci restano dove sono, con l'altro davanti.
  • A metà del cambio di nome le lettere vecchie e quelle nuove si sovrapponevano nel mezzo dell'insegna e si leggeva un pasticcio: ora le vecchie escono più in fretta e le nuove partono un poco dopo.
  • L'anello del fuoco intorno all'icona toccava il bordo basso dell'insegna: la barretta e tutto quello che ci pende sono saliti di quasi un pixel e l'anello è disegnato dentro il suo riquadro.
  • A riposo il ciclo non si fermava per quattro secondi: il risolutore lascia un movimento di circa un pixel al secondo, invisibile. La soglia ora è di 3 pixel al secondo, cioè un'oscillazione più piccola di due decimi di pixel.

Librerie

GSAP 3.15.0, Fraunces (font variabile) 5.3.0.

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

Collaudo

Provata il 6 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