Scroll orizzontale come Lenis: rifarlo con Motion
Come si fanno le card che scorrono di lato mentre scorri in basso? Lo scroll orizzontale di Lenis rifatto con Motion, accessibile, con prompt pronto.


Scorri in basso e, invece di scendere, una fila di card scivola di lato: è lo scroll orizzontale che vedi sul sito di Lenis. Per rifarlo bastano una sezione molto alta, un riquadro che resta fermo sullo schermo e poche righe di Motion. Qui trovi come funziona, il prompt per farlo costruire a un agente AI e i controlli per non lasciare indietro tastiera, telefono e chi ha spento le animazioni.
Cos'è
È un effetto scroll-linked, cioè legato allo scroll: il movimento dipende da dove sei nella pagina, non da un timer. Scorri un po', la fila si muove un po'. Ti fermi, si ferma. La sezione si "blocca" sullo schermo, il tuo scroll verticale diventa movimento laterale e, finita la fila, la pagina riprende a scendere.
Lenis è una libreria gratuita e open source per lo smooth scroll (la pagina scivola morbida con la rotella invece di andare a scatti), creata dallo studio darkroom.engineering. La sua home è una lezione di scorrimento: un logo rosa gigante, poi il titolo "Why smooth scroll?" fermo a sinistra mentre a destra scorrono blocchi di testo, poi la sezione "Lenis runs the web". È quella che rifacciamo.

Ogni card mostra un sito che usa Lenis, con il nome e lo studio che l'ha fatto, come "Lando Norris" di OFF+BRAND o "Grand Theft Auto VI" di Rockstar Games. In una nostra registrazione, con una finestra larga 1.440 pixel, circa 300 pixel di scroll spostavano la fila di circa 205 pixel di lato. Su una finestra grande come un telefono, invece, le card erano una semplice lista verticale. Dagli stili sembra che la parte bloccata usi position: sticky, un'impostazione CSS che tiene fermo un riquadro mentre la sezione che lo contiene scorre. Come sia costruito il resto non lo sappiamo, e non tiriamo a indovinare.

Perché serve
Una lunga lista di cose da mostrare, sullo schermo, diventa un muro. Questo effetto la trasforma in un piccolo spettacolo, per quattro motivi:
- Segue la tua mano. Niente parte da solo: decidi tu la velocità e puoi fermarti a metà. Un movimento che risponde a te trasmette calma, uno con il suo timer sembra un'esibizione.
- Una cosa alla volta. Mentre la fila scorre, è l'unica cosa che chiede attenzione. Prima blocchi, poi muovi.
- Il cambio di direzione ha un senso. Il movimento laterale dice: questa è una collezione, sfogliala. Come scorrere i libri su uno scaffale.
- Sa quando farsi da parte. Sul telefono rinuncia al trucco e mostra una lista semplice, più comoda con il pollice.
Funziona ovunque ci sia una piccola serie di cose da sfogliare: le camere di un agriturismo, i piatti del menu di stagione, i progetti di uno studio di architettura, la nuova collezione di un negozio online.
Come si fa
La nostra demo, fatta per questo articolo, è un file HTML, uno CSS e uno JavaScript, con Motion caricato da una CDN (un server pubblico che ospita librerie, così non installi niente). Motion è una libreria di animazione che funziona con React, Vue o JavaScript semplice.
- Una sezione alta con un riquadro sticky dentro. La sezione è molto più alta dello schermo: quell'altezza in più è la pista su cui avviene il movimento laterale. Dentro, un riquadro resta fermo mentre scorri lungo la pista. Nella demo la sezione ha un'etichetta per i lettori di schermo, "Six small lessons", e contiene un titolo e una lista di sei link, uno per card: Spacing, Type, Color, Motion, Focus e Mobile.
- Prima una fila semplice. Di base la fila di card (nella demo si chiama track) è una riga orizzontale da scorrere con il dito, con lo scroll snap, una funzione CSS che fa fermare ogni card precisa sul bordo. Se lo script non parte, chi legge ha comunque una fila che funziona.
- Poi il trucco, solo se serve. Lo script aggiunge alla sezione la classe is-linked. In quella modalità la sezione prende un'altezza salvata in una variabile CSS, il riquadro diventa sticky, alto quanto lo schermo (100vh) e nasconde quello che esce dai bordi, e la fila diventa larga quanto tutte le sue card in fila.
- Misura il viaggio. Lo script calcola quanta strada deve fare la fila: larghezza della fila meno larghezza dello schermo. Poi rende la sezione più alta dello schermo esattamente di quella misura. Così un pixel di scroll sposta la fila di un pixel di lato.
- Collega la fila allo scroll. Un'animazione laterale con animate() di Motion, passata a scroll(), che la fa avanzare con lo scroll invece che con il tempo. Con offset "start start" e "end end" parte quando la cima della sezione tocca la cima dello schermo e finisce quando il fondo tocca il fondo. Con ease linear la velocità resta costante.
- Accendilo solo quando ha senso. Lo script controlla che lo schermo sia largo almeno 768 pixel e che non sia attivo riduci movimento. Se manca una delle due, resta la fila del passo 2. Rifà i calcoli quando la finestra cambia misura o cambia l'impostazione.
- Sistema la tastiera. La fila è spostata solo con una trasformazione CSS, quindi premendo Tab il focus può finire su una card fuori schermo. Un piccolo ascoltatore dell'evento focusin fa scorrere la pagina fino a mostrare la card selezionata, e un contorno spesso 4 pixel dice sempre dove sei.
Pronto da copiare, per un agente AI che scrive codice:
Costruisci una sezione con scroll orizzontale legato allo scroll verticale, in un file HTML, uno CSS e uno JavaScript. Usa Motion caricato da CDN, versione JavaScript semplice. Contenuto: una sezione con etichetta accessibile "[nome della sezione]", un titolo e una lista di [6] link, uno per card: [titolo card 1], [titolo card 2], [...]. Comportamento: 1. Base, senza script: la fila di card è una riga orizzontale da scorrere con il dito, con scroll snap. 2. Lo script aggiunge alla sezione la classe is-linked solo se lo schermo è largo almeno 768 pixel e prefers-reduced-motion non è attivo. Altrimenti resta la fila base. 3. In modalità is-linked: un riquadro interno sticky in cima, alto 100vh, con overflow nascosto; la fila larga quanto tutte le card. 4. Misura la distanza: larghezza della fila meno larghezza dello schermo. Rendi la sezione più alta dello schermo esattamente di quella distanza, tramite una variabile CSS. 5. Anima la fila in orizzontale con animate() e collegala a scroll() con offset ["start start", "end end"] ed ease linear. 6. Ricalcola tutto quando cambia la misura della finestra o l'impostazione di movimento ridotto. 7. Accessibilità: con focusin, se una card riceve il focus, scorri la pagina finché quella card è visibile. Contorno di focus spesso 4 pixel. Non nascondere le card fuori schermo con aria-hidden o display: none. Alla fine dimmi cosa non hai potuto provare in un browser.
Se lavori in React, chiedi lo stesso effetto con gli hook useScroll e useTransform di Motion. Lenis invece non serve: la demo usa il normale scroll del browser, Lenis aggiunge sopra la sensazione di scivolamento se la vuoi.
Prova piccola
Dieci minuti, cinque controlli:
- Scorri e fermati. La fila si deve fermare quando ti fermi. Se continua da sola, non è legata allo scroll.
- Arriva in fondo. L'ultima card deve arrivare al bordo proprio quando la pagina riprende a scendere. Se la pagina riparte prima o resta bloccata dopo, la pista non è lunga quanto il viaggio.
- Solo tastiera. Premi Tab più volte: ogni card selezionata deve comparire sullo schermo, con il contorno ben visibile.
- Finestra stretta. Sotto i 768 pixel deve comparire la fila semplice da sfogliare.
- Riduci movimento. Attivalo nelle impostazioni e ricarica: niente blocco, solo la fila semplice.


Attenzione a
- Il focus fuori schermo è il bug nascosto. Senza l'ascoltatore focusin, chi usa la tastiera finisce su un link che non vede.
- Non nascondere le card ai lettori di schermo. Sono fuori schermo solo per gli occhi: la trasformazione sposta pixel, non contenuti. Lascia una vera lista di veri link.
- Telefono. Una galleria laterale comandata dallo scroll verticale è difficile da controllare con il pollice. Lì vince la fila semplice, come fa anche Lenis.
- Una volta sola. Deve essere l'unico grande effetto di scroll della pagina, o smette di essere una sorpresa.
- Animazioni solo CSS. I browser più recenti sanno legare animazioni allo scroll anche con il solo CSS, e secondo la documentazione di Motion scroll() usa questa funzione quando può. Controlla sulla documentazione di Motion prima di contarci.
Il passo dopo: prendi una piccola serie del tuo sito, come i progetti, le camere o i prodotti, e prova il prompt su una pagina di prova. Se vuoi iniziare con un movimento più semplice, guarda la striscia di testo infinita in CSS. Per capire chi fa questo lavoro tra design e codice, leggi cos'è un design engineer.
Questa pillola nasce da un'analisi di Alek su Medium. Grazie a darkroom.engineering per aver reso Lenis open source e per una home che vale la pena studiare.
In breve: Uno scroll orizzontale riuscito segue la mano di chi scorre, ha una pista lunga esattamente quanto il viaggio e sa farsi da parte con riduci movimento, da tastiera e sul telefono.
Newsletter
L'AI che funziona davvero, nella tua casella.
Le nuove pillole, gli strumenti che usiamo e quello che impariamo sui progetti. Poche mail, solo quando c’è qualcosa di utile.


