
Il menu di condivisione a moduli
Menu, Transizioni, Hover, Testo
NuovaGratis
Nello stile minimal: il menu a tutto schermo di uno studio di design. Le voci sono scritte piccole e leggere, una sotto l'altra, e una riga di lettura chiusa da due filetti sottili le segue col puntatore, su una molla: dentro la riga le stesse voci sono grandi, piene e larghe, una seconda copia della lista ritagliata dalla riga come da una lente. Le righe piccole si scostano per farle posto e passano dentro la riga senza salti, prendendo peso man mano che arrivano al centro.
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 reading line menu</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/full.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the full-screen menu of a design studio. At rest only a small Menu button. Open, the links are set small and
light, one under the other, and a reading line closed by two hairlines follows the pointer (the finger, the
arrow keys) on a spring: inside it the same links are set big, heavy and wide, a copy of the list cut out by the
line like a reading lens, and the rows pass in and out of it without a jump -->
<div class="reader" data-frame>
<button class="toggle" type="button" aria-expanded="false" aria-controls="reader-menu" data-toggle data-autoclic>
<span class="toggle__words" aria-hidden="true">
<span class="toggle__word" data-word-open>Menu</span>
<span class="toggle__word" data-word-close>Close</span>
</span>
<span class="toggle__icon" aria-hidden="true">
<i class="toggle__line" data-line><b></b></i>
<i class="toggle__line" data-line><b></b></i>
</span>
<span class="sr" data-toggle-name>Open the menu</span>
</button>
<nav class="menu" id="reader-menu" aria-label="Main" data-menu inert>
<ul class="menu__list" data-list>
<li class="menu__item"><a class="row" href="#work" aria-current="page" data-row><span class="row__mask"><span class="row__word" data-word>Work</span></span><span class="sr" data-note>Selected projects</span></a></li>
<li class="menu__item"><a class="row" href="#studio" data-row><span class="row__mask"><span class="row__word" data-word>Studio</span></span><span class="sr" data-note>People and place</span></a></li>
<li class="menu__item"><a class="row" href="#services" data-row><span class="row__mask"><span class="row__word" data-word>Services</span></span><span class="sr" data-note>Identity, type, motion</span></a></li>
<li class="menu__item"><a class="row" href="#journal" data-row><span class="row__mask"><span class="row__word" data-word>Journal</span></span><span class="sr" data-note>Essays and process</span></a></li>
<li class="menu__item"><a class="row" href="#careers" data-row><span class="row__mask"><span class="row__word" data-word>Careers</span></span><span class="sr" data-note>Open roles</span></a></li>
<li class="menu__item"><a class="row" href="#contact" data-row><span class="row__mask"><span class="row__word" data-word>Contact</span></span><span class="sr" data-note>Say hello</span></a></li>
</ul>
<!-- the reading line: a white band that hides the small rows, closed by two hairlines -->
<div class="strip" aria-hidden="true" data-strip>
<span class="strip__fill" data-fill></span>
<span class="strip__rule" data-rule-top><i data-rule></i></span>
<span class="strip__rule" data-rule-bottom><i data-rule></i></span>
</div>
<!-- the lens: a copy of the list, set big, cut out by the reading line (filled in by the script) -->
<div class="lens" aria-hidden="true" data-lens></div>
</nav>
</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>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.
31 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 «Il menu con la riga di lettura» da Animorio e adattala al mio sitoLe voci vere sono link piccoli, in Roboto Flex a 16 pixel, peso 340, una riga ogni 42 pixel. Lo script ne fa una seconda copia nascosta ai lettori di schermo, in un livello sopra, con la stessa parola a 66 pixel e la nota di ogni voce. Il livello è ritagliato con un clip-path inset in pixel che segue i due filetti, e sotto di lui una fascia bianca della stessa altezza copre le voci piccole: fuori dalla striscia si vede solo la lista piccola, dentro solo quella grande. La dimensione ottica del carattere segue da sola la grandezza, quindi le due copie hanno anche il disegno giusto per la loro misura.
Se c è il centro della striscia, y il centro di una riga piccola e M il rapporto fra l'altezza della striscia (104) e quella di una riga (42), la riga grande sta a c + (y - c) · M. Quando la striscia è su una voce, la voce dopo è esattamente un'altezza di striscia più in basso, appena fuori dal filetto; a metà strada fra due voci se ne vedono due metà, una sopra e una sotto. La riga che esce da un filetto è proprio quella che entra, senza salti, come sotto una lente vera. Il peso (da 430 a 780) e la larghezza (da 94 a 118) di ogni riga grande dipendono dalla sua distanza dal centro, con una curva morbida: la parola si riempie arrivando.
La striscia è più alta di una riga, quindi coprirebbe le voci vicine. Le voci piccole invece si spostano: quelle sopra la striscia salgono di (104 - 42) / 2 = 31 pixel, quelle sotto scendono di altrettanto, e quella dentro attraversa la striscia con la stessa mappa della lente, più veloce e nel verso contrario. La mappa è continua, quindi nessuna voce salta quando la striscia passa, e nessuna resta nascosta. Ogni voce piccola sfuma mentre la striscia la raggiunge, così un filetto non taglia mai a metà una parola piccola.
Con le voci scostate, il punto del puntatore non è più la voce che c'era: guardato con la striscia in movimento, la risposta cambiava mentre la striscia andava e la striscia gli correva dietro fino in fondo. Ora la lista si legge com'è con la striscia ferma sulla sua voce: dentro la striscia è la voce della striscia, sopra o sotto è la voce piccola che c'è lì, tolto lo scostamento. Letta così la risposta non cambia mentre la striscia arriva. Il centro della striscia va alla voce su una molla (SPRING, passi da 1/240 di secondo, mai più di 1/30 per fotogramma) con un poco di sporgenza verso il puntatore (LEAN).
Una timeline GSAP: il pulsante scivola dal centro del riquadro al suo angolo (expo.inOut), le voci salgono dalle maschere a 45 millesimi l'una dall'altra, i due filetti si disegnano con scaleX da sinistra, poi la striscia si apre da zero alla sua altezza con un back.out leggero. Alla chiusura il contrario: la striscia si chiude, i filetti si ritirano verso destra, le voci scendono dall'ultima e il pulsante torna al centro. Il ciclo dei fotogrammi gira solo finché la molla o la timeline si muovono.
Il pulsante ha aria-expanded e aria-controls; chiuso, il menu è inert e nascosto. Aperto da tastiera il fuoco va sulla pagina corrente, le frecce, Home e Fine portano la striscia di voce in voce con una cornice sottile intorno alla parola grande, Tab gira fra il pulsante e le voci, Esc chiude e rimette il fuoco sul pulsante. Il clic dell'anteprima (detail 0, senza un tasto appena premuto) fa un giro intero: apre, legge la lista giù e su riga per riga, sceglie una voce e chiude.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
LENS_WEIGHT | script.js | [430, 780] | Il peso di una voce grande al bordo della striscia e al suo centro (da 100 a 1000). |
LENS_WIDTH | script.js | [94, 118] | La larghezza di una voce grande al bordo della striscia e al suo centro, sull'asse della larghezza (da 25 a 151). |
SMALL_WEIGHT | script.js | 340 | Il peso delle voci piccole. |
SPRING | script.js | [180, 22] | La molla della striscia: quanto è rigida e quanto è frenata (meno freno, più rimbalzo). |
LEAN | script.js | 0.1 | Quanto la striscia si sporge verso il puntatore dentro la sua voce (0, resta ferma sulla voce). |
STAGGER | script.js | 0.045 | I secondi fra una voce e l'altra all'apertura e alla chiusura. |
PRESS | script.js | 6 | Di quanti pixel si stringe la striscia sulla voce scelta. |
STRETCH | script.js | 0.025 | Quanto si allunga la striscia dietro di sé correndo (al massimo 6 pixel). |
Per il menu a tutto schermo di chi lavora con le parole e l'immagine: uno studio di design o di architettura, un'agenzia, una rivista, il portfolio di un fotografo o di un tipografo. Sta bene con cinque, sei o sette voci corte su un fondo chiaro e vuoto; la nota di ogni voce (data-note) dice in due parole cosa c'è dietro. Sul sito vero il riquadro diventa fisso a tutto schermo e il pulsante resta nel suo angolo: come si fa è scritto in cima a style.css.
Sotto i 560 pixel il riquadro è largo quanto lo schermo meno 32 (358 a 390), le voci piccole sono a 15 pixel ogni 40, la striscia è alta 84 e le parole grandi sono a 47 pixel; sotto i 400 le note a destra non ci sono. Le stesse animazioni: il pulsante scivola nell'angolo, le voci salgono, i filetti si aprono. La striscia segue il dito che scorre sulla lista, come il mouse; alzando il dito si posa sulla sua voce, e un tocco senza scorrere sceglie la voce toccata e chiude il menu.
Niente scivolamenti né molle: premendo Menu il pulsante sfuma e ricompare già nel suo angolo, la lista e la striscia compaiono in dissolvenza già al loro posto. La striscia passa da una voce all'altra di colpo, con una breve dissolvenza delle parole grandi, senza sporgersi né allungarsi; il pulsante non apre le sue linee. Alla chiusura tutto sfuma e il pulsante ricompare al centro.
GSAP 3.15.0, Roboto Flex (font variabile, con gli assi della larghezza, del peso e della dimensione ottica) 5.3.0.
Compressi con gzip, i tre file della demo pesano 10 KB; le librerie: GSAP 28 KB.
Provata il 16 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.