Ecco una piccola interazione che rende i contenuti long-form molto più coinvolgenti: un video che segue il lettore mentre scorre, rimpicciolendo dolcemente nell’angolo in basso a destra come un player picture-in-picture. Lo costruiamo con le interazioni scroll GSAP di Webflow, lo sticky positioning, un po’ di calc e una variabile Webflow ingegnosa che tiene tutto pulito.
La parte interessante non è l’effetto — è la tecnica dietro: guidare tre transform separati con una sola variabile animata, e compensare i capricci di layout che lo sticky positioning introduce. Padroneggiali e questo pattern diventa riutilizzabile ovunque.
Come funziona
È un trigger di scroll discreto, non uno scrub. Non vogliamo che la forma del video sia legata in continuazione alla posizione di scroll; vogliamo che cambi stato una volta, al superamento di una soglia. Quindi l’interazione scroll sul wrapper del video usa trigger actions (non scrub on scroll), con leave → play (parte quando il wrapper inizia a lasciare il viewport) e enter back → reverse (annulla quando rientra del tutto). Le soglie sono impostate così che il cambio avvenga quando il bordo superiore del wrapper raggiunge il bordo superiore del viewport (soglia end: top/top).
Sticky sono tre proprietà, quindi fanne una classe. Rendere sticky il video non è solo position: sticky — servono anche un offset top (0) e uno z-index alto (100) così resta sopra il contenuto su cui scorre. Dato che devono cambiare insieme, raggruppale in una combo class (is-sticky) e invertila con una action set. (Tieni una copia del wrapper con quella classe nello style guide così Webflow non la elimina.)
Una variabile guida tre transform. Il transform finale è un translateX, un translateY e uno scale(0.4), tutti scritti come espressioni calc in una proprietà transform custom (i controlli transform del pannello stile non accettano calc), con transform-origin: top right così rimpicciolisce verso l’angolo. La posizione orizzontale è calc(50vw - 50% - 2rem) (spingi al centro del viewport, tira indietro di metà della sua larghezza, poi il padding di pagina); quella verticale è calc(100vh - 40% - 2rem). Animare tre variabili separate con calc è fragile, quindi creiamo una sola variabile numerica (transform-factor, 0 → 1) e moltiplichiamo ogni formula per essa: translateX((…) * factor), translateY((…) * factor), e — il trucco elegante — scale(calc(1 - 0.6 * factor)) così lo scale va da 1 (factor 0) a 0.4 (factor 1). Una singola action animate variable da 0 a 1 guida tutti e tre.
Compensare lo shift dello sticky. Un translateY insieme a position: sticky porta il layout finale troppo in basso. Il fix è un bottom margin sul wrapper pari alla sua altezza scalata — calc(100vh - 768px * 0.5625 - 2rem), dove 768px è la larghezza del wrapper su desktop e 0.5625 il rapporto d’altezza 16:9 — poi un top margin negativo sull’elemento sotto per annullare il gap che apre. (I margin in percentuale si riferiscono alla larghezza del parent, e il margin si risolve prima dello scale: per questo si usa la forma in pixel.) Infine, questo effetto non ha senso su schermi piccoli o per chi non gradisce il movimento, quindi il conditional playback lo disabilita da tablet in giù e quando è attivo prefers-reduced-motion.
Come si usa
-
Prepara il wrapper. Video in un wrapper con max width,
margin-inline: auto,aspect-ratio: 16/9etransform-origin: top right. Crea una combo classis-stickyconposition: sticky,top: 0,z-index: 100(tieni una copia nello style guide). -
Aggiungi la variabile transform. Crea una variabile numerica
transform-factor(default 0). Nella proprietàtransformcustom del wrapper, scrivitranslateX((50vw - 50% - 2rem) * factor) translateY((100vh - 40% - 2rem) * factor) scale(calc(1 - 0.6 * factor)). -
Costruisci l’interazione scroll. Sul wrapper: interazione scroll, trigger actions, leave → play, enter back → reverse, soglia end top/top. Aggiungi una action set che fa il toggle della classe
is-stickya 0s, e una action animate variable che portatransform-factorda 0 → 1 (es. 0.3s, sine in-out). -
Compensa il layout. Aggiungi al wrapper il bottom margin
calc(100vh - 768px * 0.5625 - 2rem), e un top margin negativo corrispondente sull’elemento successivo. -
Proteggilo. Nel conditional playback, imposta no animation per i breakpoint da tablet in giù e per prefers-reduced-motion. Pubblica e prova sul link live.