Puoi costruire un reveal staggered slide-and-fade responsive in Webflow senza scrivere una sola riga di JavaScript — bastano un attributo e un piccolo blocco di CSS costruito attorno alla proprietà transition-delay. È la stessa idea che abbiamo usato per le animazioni del testo, solo che ora si adatta ai breakpoint, sopravvive a qualsiasi numero di colonne e funziona persino con il CMS.
Il motivo per cui serve un trucco è che Webflow non riesce a “vedere” una riga. Può far partire un’animazione quando l’intera griglia entra in viewport, o quando lo fa un singolo elemento — ma non quando una riga intera attraversa lo schermo, che è esattamente ciò che serve a uno stagger. I workaround nativi (spezzare ogni riga in una sua griglia) crollano non appena le colonne si riorganizzano a un breakpoint più piccolo, e non possono toccare i singoli elementi del CMS.
Così, invece di combattere Webflow, lasciamo fare al CSS la parte in cui è bravo. L’interazione resta banale; l’intelligenza vive in poche righe di CSS che puoi leggere, capire e modificare per qualsiasi layout.
Come funziona
L’interazione è quasi vuota, di proposito. Ogni elemento della griglia porta due transizioni CSS — una per il move transform, una per l’opacity (nel progetto di riferimento entrambe durano 800ms, con ease per l’opacity e ease-out cubic per il move). L’interazione scroll-into-view di Webflow fa poi il minimo indispensabile: due action, ciascuna con durata zero e senza easing, che riportano l’elemento a translateY(0) e opacity: 100%. Imposta il trigger perché agisca sulla classe, così costruendola una volta si applica a tutti i fratelli e il codice generato da Webflow resta leggero. Da sola non produce nulla di visibile — gli elementi sono già nella loro posizione finale — ed è qui che entra il CSS.
Il CSS imposta il punto di partenza e il ritmo. Un blocco di CSS custom punta ogni elemento tramite il suo attributo ([fc-css-staggered="item"]) e gli assegna uno stato iniziale: spostato in basso (circa 3rem sull’asse Y) e opacity: 0. Quando un elemento entra in viewport, la sua transizione lo porta da quel punto di partenza allo stato a riposo. Lo stagger non è altro che un transition-delay diverso per colonna: la prima colonna parte subito, la seconda un attimo dopo, e così via, così una riga sembra comparire a onde.
:nth-child() è tutto il motore. Per dare a ogni colonna il suo delay, il codice usa un “building block” per colonna, con questa forma: [fc-css-staggered="item"]:nth-child(Nn - i). Due numeri fanno tutto il lavoro: N, il coefficiente prima di n, è uguale al numero di colonne a quel breakpoint; i, il numero dopo il meno, è l’indice della colonna, che va da N - 1 per la prima colonna fino a 0 per l’ultima. Così in una griglia a quattro colonne, 4n - 3 prende la prima colonna, 4n - 2 la seconda e 4n la quarta.
Le media query lo rendono responsive. Poiché una griglia cambia il numero di colonne a seconda del breakpoint, avvolgi ogni set di building block in una query @media (min-width: …) — 480px (landscape), 768px (tablet), 992px (desktop), e così via. Ogni query sovrascrive quella sotto, così definisci solo ciò che cambia. È questa l’idea chiave: adattarsi a un nuovo layout non è mai una riscrittura, solo far combaciare il coefficiente con il numero di colonne e aggiungere un building block per colonna.
Come si usa
-
Costruisci la griglia e marca gli elementi. Dai a ogni elemento dentro la griglia l’attributo
fc-css-staggeredcon valoreitem. Poiché l’attributo vive su ogni elemento (non su una classe), configura il primo elemento e poi duplicalo — le copie ereditano l’attributo automaticamente. -
Aggiungi le due transizioni all’elemento. Sull’elemento della griglia, aggiungi una transizione per il move transform e una per l’opacity (es.
800ms,ease-out cubicper il move eeaseper l’opacity). Sono queste ad animare davvero; l’interazione non fa che ribaltare lo stato finale. -
Costruisci un’interazione scroll-into-view minimale. Due action — move a
translateY(0)e opacity a100%— entrambe con durata0e senza easing. Imposta un offset (circa20%) e, nelle impostazioni del trigger, scegli class così si applica a ogni elemento con quella classe. -
Incolla il CSS. Mettilo nel componente Global Styles (tutto il sito), nell’
<head>della pagina (solo quella pagina), o in Site Settings → Custom Code → head (tutto il sito). Il blocco imposta lo stato iniziale e untransition-delayper colonna dentro una media query per ogni breakpoint. -
Taralo sul tuo layout. Per ogni breakpoint, tieni un building block per colonna, imposta il coefficiente prima di
nsul numero di colonne, imposta l’indice dopo il meno daN - 1fino a0, e dai a ogni colonna il suo delay. Per aggiungere un nuovo breakpoint (diciamo un layout a cinque colonne a1440px), copia una media query, cambia il suomin-width, porta il coefficiente a cinque, aggiungi un quinto building block e imposta i suoi delay. -
Due griglie, o il CMS. Per una seconda griglia, dai ai suoi elementi
fc-css-staggered="item-2", duplica il CSS e sostituisciitemconitem-2nei selettori — i due stagger restano indipendenti. Per una collection list, metti l’attributo sulla collection item; non cambia nient’altro, ed è proprio per questo che questo approccio funziona dove quello nativo non può.
Ecco la forma del CSS, ricostruita dalla spiegazione — lo stato iniziale, poi una media query per breakpoint con un building block per colonna:
/* Stato iniziale: ogni elemento parte spostato in basso e invisibile */
[fc-css-staggered="item"] {
transform: translateY(3rem);
opacity: 0;
}
/* Portrait — 1 colonna, nessuno stagger */
[fc-css-staggered="item"]:nth-child(1n - 0) { transition-delay: 0ms; }
/* Landscape — 2 colonne, da 480px */
@media screen and (min-width: 480px) {
[fc-css-staggered="item"]:nth-child(2n - 1) { transition-delay: 0ms; } /* colonna 1 */
[fc-css-staggered="item"]:nth-child(2n - 0) { transition-delay: 100ms; } /* colonna 2 */
}
/* Tablet — 3 colonne, da 768px */
@media screen and (min-width: 768px) {
[fc-css-staggered="item"]:nth-child(3n - 2) { transition-delay: 0ms; } /* colonna 1 */
[fc-css-staggered="item"]:nth-child(3n - 1) { transition-delay: 100ms; } /* colonna 2 */
[fc-css-staggered="item"]:nth-child(3n - 0) { transition-delay: 300ms; } /* colonna 3 */
}
/* Desktop — 4 colonne, da 992px */
@media screen and (min-width: 992px) {
[fc-css-staggered="item"]:nth-child(4n - 3) { transition-delay: 0ms; } /* colonna 1 */
[fc-css-staggered="item"]:nth-child(4n - 2) { transition-delay: 100ms; } /* colonna 2 */
[fc-css-staggered="item"]:nth-child(4n - 1) { transition-delay: 300ms; } /* colonna 3 */
[fc-css-staggered="item"]:nth-child(4n - 0) { transition-delay: 600ms; } /* colonna 4 */
}
/* Aggiungi un breakpoint a 5 colonne allo stesso modo:
@media screen and (min-width: 1440px) {
[fc-css-staggered="item"]:nth-child(5n - 4) { transition-delay: 0ms; }
[fc-css-staggered="item"]:nth-child(5n - 3) { transition-delay: 100ms; }
[fc-css-staggered="item"]:nth-child(5n - 2) { transition-delay: 300ms; }
[fc-css-staggered="item"]:nth-child(5n - 1) { transition-delay: 600ms; }
[fc-css-staggered="item"]:nth-child(5n - 0) { transition-delay: 1000ms; }
} */
Un limite onesto da conoscere: tutto qui presuppone che ogni riga abbia lo stesso numero di colonne (può cambiare tra i breakpoint, ma non da riga a riga). Righe con numeri di colonne misti rompono la matematica di :nth-child — un rompicapo per un altro giorno.