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 andare oltre i breakpoint già presenti nel blocco, copia una media query, cambia il suomin-width, porta il coefficiente al nuovo numero di colonne, aggiungi un building block in più 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 il CSS dal cloneable — lo stato iniziale, poi una media query per breakpoint con un building block per colonna. Nota il prefisso html:not(.wf-design-mode) sullo stato iniziale: dato che quello stato nasconde gli elementi, limitarlo a “non il Designer” li tiene visibili mentre costruisci.
<style>
/* 'n' is a number that can take all integer values starting from 1 */
/* The number before 'n' is the number of columns within that breakpoint */
/* The number after minus sign (-) is the index of the current column (from the number of columns minus 1 to 0) */
/* INITIAL STATES */
html:not(.wf-design-mode) [fc-css-staggered = item] {
opacity: 0;
transform: translateY(3rem)
}
/* PORTRAIT BREAKPOINT */
[fc-css-staggered = item]:nth-child(1n - 0) {
transition-delay: 0ms;
}
/* LANDSCAPE BREAKPOINT */
@media screen and (min-width: 480px)
{
[fc-css-staggered = item]:nth-child(2n - 1) {
transition-delay: 0ms;
}
[fc-css-staggered = item]:nth-child(2n - 0) {
transition-delay: 100ms;
}
}
/* TABLET BREAKPOINT */
@media screen and (min-width: 768px)
{
[fc-css-staggered = item]:nth-child(3n - 2) {
transition-delay: 0ms;
}
[fc-css-staggered = item]:nth-child(3n - 1) {
transition-delay: 100ms;
}
[fc-css-staggered = item]:nth-child(3n - 0) {
transition-delay: 300ms;
}
}
/* DESKTOP BREAKPOINT */
@media screen and (min-width: 992px)
{
[fc-css-staggered = item]:nth-child(4n - 3) {
transition-delay: 0ms;
}
[fc-css-staggered = item]:nth-child(4n - 2) {
transition-delay: 100ms;
}
[fc-css-staggered = item]:nth-child(4n - 1) {
transition-delay: 300ms;
}
[fc-css-staggered = item]:nth-child(4n - 0) {
transition-delay: 600ms;
}
}
/* 1440 BREAKPOINT */
@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;
}
}
</style>
La seconda griglia riceve la sua copia dello stesso blocco con item sostituito da item-2 — ed è un buon esempio di quanto la messa a punto sia specifica per griglia: nel cloneable quella griglia è già a 2 colonne in portrait (quindi 2n - 1 → 0ms, 2n - 0 → 100ms già alla base), tiene 2/3/4 colonne tra landscape, tablet e desktop, e si ferma lì senza nessuna query a 1440px. Stesso motore, numeri diversi.
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.