Vai al contenuto
animorio
EN
Torna alla libreria

La parola con le maniglie

Testo, HoverGSAP, Solo CSSImpegnativaPeso compresso: Demo 9,5 KBGSAP 28 KBGratisScarica lo zip

Una parola dentro un riquadro di selezione, come un livello in un programma di grafica: le quattro maniglie funzionano, e tirando un angolo la parola si ricompone per riempire il riquadro, con l’asse di larghezza del carattere.

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 word with handles</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/anybody@5.3.0/wdth.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>
  <!-- the board is one screen: two rulers, the word inside its selection frame, a colleague's cursor that types -->
  <main class="board" data-board>
    <div class="ruler ruler--x" data-ruler="x" aria-hidden="true">
      <span class="ruler__band"></span>
      <span class="ruler__numbers" data-numbers="x"></span>
      <span class="ruler__mark" data-mark="x"></span>
    </div>
    <div class="ruler ruler--y" data-ruler="y" aria-hidden="true">
      <span class="ruler__band"></span>
      <span class="ruler__numbers" data-numbers="y"></span>
      <span class="ruler__mark" data-mark="y"></span>
    </div>
    <span class="ruler__corner" aria-hidden="true"></span>

    <header class="top">
      <p class="brand">Offcut</p>
      <p class="top__line">A small studio for printed things</p>
    </header>

    <!-- dashed guides along the frame's edges, shown while a corner is being pulled -->
    <div class="guides" aria-hidden="true"><i class="guide guide--left"></i><i class="guide guide--right"></i><i class="guide guide--top"></i><i class="guide guide--bottom"></i></div>

    <div class="frame" data-frame>
      <h1 class="word" data-word aria-label="Offcut"><span class="word__letter" aria-hidden="true">O</span><span class="word__letter" aria-hidden="true">F</span><span class="word__letter" aria-hidden="true">F</span><span class="word__letter" aria-hidden="true">C</span><span class="word__letter" aria-hidden="true">U</span><span class="word__letter" aria-hidden="true">T</span></h1>
      <span class="frame__edge frame__edge--top" aria-hidden="true"></span>
      <span class="frame__edge frame__edge--right" aria-hidden="true"></span>
      <span class="frame__edge frame__edge--bottom" aria-hidden="true"></span>
      <span class="frame__edge frame__edge--left" aria-hidden="true"></span>
      <button class="handle handle--nw" type="button" data-handle="nw" aria-label="Top left corner: drag, or use the arrow keys, to resize the word"></button>
      <button class="handle handle--ne" type="button" data-handle="ne" aria-label="Top right corner: drag, or use the arrow keys, to resize the word"></button>
      <button class="handle handle--sw" type="button" data-handle="sw" aria-label="Bottom left corner: drag, or use the arrow keys, to resize the word"></button>
      <button class="handle handle--se" type="button" data-handle="se" aria-label="Bottom right corner: drag, or use the arrow keys, to resize the word"></button>
      <p class="frame__size" data-size aria-live="off"><span data-size-box>0 × 0</span><span class="frame__axis" data-size-axis>width 100</span></p>
    </div>

    <!-- a colleague: the cursor, the name and the bubble where the greeting is typed -->
    <div class="peer" data-peer aria-hidden="true">
      <svg class="peer__arrow" viewBox="0 0 24 26" width="24" height="26"><path d="M2 2 L2 21 L7.4 16.2 L11 24 L14.6 22.4 L11.2 14.8 L18.6 14.4 Z"/></svg>
      <span class="peer__name">Ines</span>
      <span class="peer__bubble" data-bubble><span data-typed></span><i class="peer__caret" data-caret></i></span>
    </div>

    <p class="hint" data-hint>Pull a corner: the word is set again to fill its frame.</p>
    <button class="replay" type="button" data-replay data-autoclic>Replay</button>
  </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.

36 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 parola con le maniglie» da Animorio e adattala al mio sito

Cosa fa

La tavola blu di uno studio inventato, quadrettata come una cianografia, con due righelli. Arriva il cursore di una collega, Ines, e nel suo fumetto si scrive «hello, we are»; poi le sei lettere di OFFCUT entrano una alla volta da destra, su una molla, e intorno si disegna il riquadro di selezione: quattro righe gialle, quattro maniglie, e sotto le sue misure. Ines cancella il saluto, prende l’angolo in basso a destra e lo tira: la parola si allarga, poi si stringe, e resta sempre a filo del riquadro. Da lì in poi le maniglie sono tue: ogni angolo si trascina col mouse, col dito o con le frecce, e i righelli segnano quanto è largo e alto il riquadro.

Come funziona

Il carattere, misurato una volta

Arrivato il carattere, lo script prende tre misure su un canvas: quanto sono alte le maiuscole, quanto sale e quanto scende il carattere, tutte come parte del corpo. Poi mette la parola a 200 px e ne legge la larghezza a ogni passo dell’asse wdth, da 50 a 150 ogni 10: undici misure, in em, che valgono a qualunque corpo.

Dall’altezza, il corpo

L’altezza del riquadro, meno un po’ d’aria sopra e sotto, è quella che devono avere le maiuscole: il corpo è quell’altezza divisa per la parte di corpo che le maiuscole occupano. La riga è alta quanto le maiuscole, e uno spostamento in giù (metà di: maiuscole, meno salita, più discesa) le mette esattamente dentro.

Dalla larghezza, l’asse

La larghezza che resta, divisa per il corpo, dice quanti em deve essere larga la parola. Fra le undici misure lo script trova le due che la contengono e interpola il valore di font-stretch. Se il riquadro chiede meno di wdth 50 o più di wdth 150 l’asse si ferma lì, e il resto lo fa uno scaleX: sotto il riquadro compare «stretched».

Le maniglie

Ogni maniglia è un bottone. Al pointerdown cattura il puntatore e si tiene la distanza fra il punto toccato e l’angolo; trascinando, quell’angolo segue e quello opposto resta fermo, fra un minimo di 150 per 64 px e i bordi della tavola. Con le frecce si sposta di 10 px, 40 con Maiusc. Al rilascio le lettere si assestano con un elastico; due clic sul riquadro lo riportano com’era.

I righelli

Quattro variabili CSS sulla tavola, --ox, --oy, --fw e --fh, dicono dov’è il riquadro: le leggono il riquadro stesso, i righelli e le guide tratteggiate. Le tacche sono tre gradienti ripetuti ogni 10, 50 e 100 px, spostati con background-position perché lo zero cada sull’angolo del riquadro; una fascia gialla ne copre larghezza e altezza, e una riga rossa segue il puntatore con gsap.quickTo, in 0,2 secondi.

L’apertura

Una timeline. Il saluto si scrive in un secondo, con un contatore che taglia la frase, e il cursore del testo lampeggia a scatti; le lettere partono 40 px più a destra, a scala 0,9, a 0,03 secondi una dall’altra, su una curva che è la soluzione di una molla (rigidità 400, smorzamento 40, massa 4); poi righe, maniglie, misure. La collega tira l’angolo chiamando la stessa funzione delle maniglie. Chi tocca una maniglia prima della fine ferma tutto e prende il comando.

Valori da cambiare

NomeFileDi partenzaCosa cambia
WEIGHTscript.js780Il peso della parola.
AXISscript.js[50, 150]I due estremi dell’asse di larghezza: da cambiare se cambi carattere.
PADscript.js[0.07, 0.13]L’aria fra parola e riquadro, come parte dell’altezza del riquadro: ai lati, e sopra e sotto.
MINscript.js[150, 64]Il riquadro più piccolo, in pixel.
GREETING, TYPE_TIMEscript.js'hello, we are', 1Cosa scrive la collega, e in quanti secondi.
LETTER_GAP, SPRINGscript.js0.03, 400 / 40 / 4I secondi fra una lettera e la successiva, e la molla su cui arrivano: rigidità, smorzamento, massa.
KEY_STEPscript.js10I pixel per ogni freccia (quattro volte tanto con Maiusc).
--blue, --yellowstyle.css#2343e6, #ffd21fIl colore della tavola, e quello di riquadro, fasce e misure.

Provali nel Playground

Quando usarla

Per il nome di uno studio, di un prodotto o di una persona in cima a una pagina che parla di design: un portfolio, un’agenzia, una fonderia, la pagina di un carattere variabile.

Sul telefono

Un righello solo, in alto. Il riquadro parte più alto, con la parola stretta, e gli angoli si trascinano col dito: intorno a ogni maniglia c’è un’area di 46 px. La collega tira meno verso destra, perché di posto ce n’è poco.

Con il movimento ridotto

Niente apertura: parola, riquadro e misure ci sono subito, la collega non compare e le lettere non rimbalzano. Le maniglie funzionano, e il bottone in basso riporta il riquadro com’era.

Trappole

  • Le misure vanno prese dopo che il carattere è arrivato (document.fonts.load): prima, canvas e pagina misurano il carattere di riserva e la parola esce dal riquadro.
  • Con un’interlinea più bassa del corpo il testo non si centra sulle maiuscole ma sulla somma di salita e discesa: senza lo spostamento calcolato, la parola sta più su o più giù del riquadro a seconda del carattere.
  • Le lettere sono inline-block, per muoverle una alla volta, e fra uno span e l’altro non c’è crenatura: la larghezza va misurata sulla parola fatta così, non su un testo normale.
  • Le maniglie vogliono touch-action: none, sennò al telefono il primo movimento se lo prende il browser e arriva un pointercancel.
  • Il punto toccato non è mai l’angolo esatto: se non si tiene quella distanza, al primo movimento il riquadro fa un salto.
  • L’apertura e le mani di chi guarda scrivono le stesse variabili: appena si tocca una maniglia la timeline va fermata e tutto portato allo stato finale, sennò le due si contendono il riquadro.

Librerie

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

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

Collaudo

Provata il 30 settembre 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