Capitolo 15

La pagina lunga

Dieci minuti di lettura sono un piccolo viaggio: chi parte vuole sapere dove si trova, quanto manca, e ritrovare il punto se si allontana. Sono i dettagli che tengono compagnia senza mettersi davanti al testo.

12 min di lettura

Il capitolo scorso parlava di componenti che si toccano una volta e finiscono. Questo cambia la scala del tempo: non un gesto da un secondo, ma una lettura da dieci minuti. La domanda diventa diversa — non «come rispondo a un click?», ma «come si tiene compagnia a chi legge per dieci minuti?». Una pagina lunga è un piccolo viaggio, e chi viaggia ha bisogni semplici: sapere dove si trova, quanto manca, ritrovare il punto se si allontana, leggere un inciso senza perdere il filo.

Sono bisogni umili, e per questo facili da trascurare. Quasi tutto il playground rincorre micro-interazioni che durano un battito; qui i dettagli devono durare, accompagnare senza stancare, restare utili al primo come al nono minuto. È un tipo di onestà particolare: il rischio non è mentire su uno stato, è fingere progresso, celebrare un traguardo che il lettore non ha ancora raggiunto, rubargli il controllo dello scroll «per aiutarlo».

Cinque dettagli, cinque compagni di lettura. E come sempre niente librerie: il browser conosce già lo scroll-spy con l’IntersectionObserver, le timeline di scroll in CSS, la Popover API, l’ancoraggio, il localStorage. Il nostro lavoro è solo orchestrarli con misura — perché il protagonista resti il testo, e i dettagli sappiano stare un passo indietro.

L’indice che dice «sei qui»

Il primo compagno è una mappa. In una pagina lunga il lettore perde facilmente il senso di dove si trova: un indice sticky glielo restituisce, e si aggiorna da solo mentre si scorre.

15.a

L’apertura

Una pagina lunga comincia con una promessa: vale la pena restare. L’indice qui di fianco non serve a impressionare, serve a rassicurare — dice quante tappe ci sono e quale stai percorrendo adesso.

La voce evidenziata non è "quella più in alto sullo schermo". È quella che stai davvero leggendo: la sezione che occupa la riga di lettura, un terzo sotto il bordo.

Il ritmo

Scorri piano e l’indice ti segue piano. Non anticipa, non si agita: l’evidenziazione si sposta quando l’occhio è davvero sulla sezione nuova, non un attimo prima.

È un IntersectionObserver a fare il lavoro, non un listener di scroll che misura tutto a ogni frame. L’osservatore vive sul compositor; il main thread resta libero per la lettura.

La misura

Un indice onesto sta in una colonna senza scroll. Se le voci diventano troppe, il segno non è "ingrandisci l’indice": è "dividi l’articolo". La forma dell’indice misura la forma del testo.

Qui le sezioni sono cinque, e cinque è già un buon numero per una lettura di dieci minuti: abbastanza tappe per orientarsi, non così tante da diventare rumore.

La tastiera

Ogni voce è un link vero, con focus visibile. Con Tab li percorri in ordine; con Invio salti alla sezione. L’indice si lascia usare con il mouse e con la tastiera senza che nessuno dei due modi sembri un ripensamento.

La voce attiva porta aria-current="location": lo screen reader annuncia "posizione corrente" mentre scorri. Il colore è il secondo segnale, non il primo.

Il congedo

Arrivati in fondo, l’indice ha esaurito il suo compito. Ti ha tenuto compagnia senza mai mettersi davanti al testo. Questo è il modo migliore per misurare se un componente è onesto: ci pensi solo quando lo cerchi.

Non c’è festeggiamento per essere arrivati qui. La fine di una lettura lunga è un gesto privato: l’indice si limita a segnare l’ultima tappa e tace.

Indice sticky · la sezione corrente si evidenzia da sola

Scorri l’articolo a destra e guarda l’indice a sinistra: la voce attiva cambia da sola. Ma la scelta del «cosa è attivo» non è banale — non è la sezione più in alto, è quella che stai davvero leggendo. Un IntersectionObserver con un rootMargin che alza la riga di lettura al 35% dal bordo decide quale sezione occupa lo sguardo, e l’evidenziazione si sposta quando l’occhio è già lì, non un attimo prima. È scroll-spy fatto sul compositor, non un listener che rimisura tutto a ogni frame.

L’indice è una vera <nav> con una lista di link in-page, e la voce attiva porta aria-current=“location”: lo screen reader annuncia «posizione corrente», il colore è il secondo segnale, non il primo. Il click scorre alla sezione in modo fluido — ma sotto prefers-reduced-motion diventa un salto netto, perché lo smooth-scroll è motion a tutti gli effetti. E quando il viewport si stringe l’indice sparisce: su schermo piccolo lo spazio va al contenuto, non a un sommario che ruba colonne.

La barra che dice «quanto manca»

Secondo compagno: l’avanzamento. Una barra sottile in cima risponde alla domanda più frequente di una lettura lunga — quanto resta? — e la risposta migliore è scolpita nel CSS, non calcolata a mano.

15.b

Il compositore di pagina

Una barra di lettura sottile, ferma in alto, è un patto silenzioso: ti dico dove sei e quanto manca, senza chiederti niente in cambio. Non è un caricamento, è una mappa di posizione.

Il suo riempimento è guidato dallo scroll di questa finestra, non dal tempo. Se ti fermi, lei si ferma; se torni indietro, lei torna indietro. È la differenza fra un indicatore onesto e una promessa di progresso.

Il segreto è dove gira il calcolo. Con animation-timeline: scroll() la barra vive sul compositor: il browser la disegna senza disturbare il main thread, e non perde un colpo nemmeno mentre l’occhio corre.

Il numero a destra, invece, lo aggiorna il JavaScript, perché il CSS anima la larghezza e non il testo. Usa cifre tabulari: quando passa da 9 a 10 la riga non sobbalza. La precisione non è vanità, è quiete.

Dove animation-timeline non esiste ancora, un piccolo script col scroll event passivo spinge la stessa barra. Stesso risultato, percorso diverso — e la versione nativa, quando c’è, vince sempre.

Sei quasi in fondo. L’ultimo tratto di una lettura lunga è quello che si guadagna con la pazienza dei primi due terzi: la barra non lo celebra, lo registra e basta.

Barra di lettura · animation-timeline: scroll() con fallback

Il riempimento della barra è legato allo scroll del contenitore con animation-timeline: scroll(): una timeline di scroll in CSS puro, zero JavaScript per il movimento. Gira sul compositor, e questo cambia tutto — non sussulta, non perde un colpo mentre l’occhio corre, non occupa il main thread. Un @supports (animation-timeline: scroll()) apre il percorso nativo; dove ancora manca, un piccolo script col scroll event passivo spinge la stessa barra. Stesso risultato, due strade, e la nativa vince sempre.

Il numero percentuale, invece, lo aggiorna il JavaScript, perché il CSS anima la larghezza e non il testo — e usa cifre tabulari, così passando da 9 a 10 la riga non sobbalza. Sotto prefers-reduced-motion non c’è nulla da togliere: questa non è un’animazione temporale, è una mappatura di posizione. Ridurre il movimento non significa nascondere informazione, e la barra resta legata allo scroll esattamente come prima. È la distinzione che il capitolo 02 ripeteva: si toglie il percorso, mai lo stato.

La nota che non ti sposta

Terzo compagno: l’inciso. La nota a piè di pagina è una grande invenzione editoriale, ma sullo schermo ha un difetto antico — il salto. Clicchi, finisci in fondo, perdi il punto. Un popover ancorato lo risolve alla radice.

15.c

Una nota che non ti sposta

La nota a piè di pagina è una grande invenzione editoriale, ma sullo schermo ha un difetto: il salto. Premi il numero e finisci in fondo, lontano dal punto in cui leggevi.

Un popover ancorato tiene la nota lì, accanto al richiamo. Leggi l’inciso, premi Esc, e il paragrafo non si è mai mosso. È la stessa idea di sempre, vestita di un’interazione più gentile.

Nota 1

Il richiamo è un <sup> con dentro un <button>: la tastiera ci arriva con Tab, lo screen reader lo annuncia come pulsante. La grafica minuscola non toglie semantica.

Nota 2

Popover API e CSS Anchor Positioning fanno il lavoro pesante: top layer, light dismiss, Esc e ancoraggio al numero. Niente libreria, niente trappola del focus fatta a mano.

Nota a piè di pagina · Popover API + CSS Anchor Positioning

Il numerino del richiamo apre una nota lì dove stai leggendo, ancorata al richiamo stesso. Sotto la pelle ci sono due API native che fanno il lavoro pesante: la Popover API (popovertarget + popover=“auto”) gestisce top layer, light-dismiss e Esc senza una riga di codice; il CSS Anchor Positioning incolla il popover al numero con position-anchor e si gira da solo verso lo spazio libero con position-try-fallbacks. Niente trappola del focus fatta a mano, niente libreria di tooltip.

Il richiamo è un <sup> con dentro un vero <button>: la tastiera ci arriva con Tab, lo screen reader lo annuncia come pulsante, e il popover ha role=“note”. La cura in più che aggiungiamo a mano è il focus restore: quando la nota si chiude — con la X, con Esc, o cliccando fuori — il focus torna al richiamo che l’aveva aperta, così la tastiera non resta orfana in cima alla pagina. È la differenza fra un componente che funziona e uno che si lascia usare anche a occhi chiusi.

Il pulsante che compare solo se serve

Quarto compagno: la scorciatoia di ritorno. In cima alla pagina un «torna su» è inutile — sei già su. Per questo non deve esserci all’inizio: deve comparire solo quando tornare in cima è diventato un viaggio.

15.d

Scendi, poi guarda in basso a destra

Scorri verso il basso. Per ora, in basso a destra, non c’è niente: sei ancora vicino alla cima, e un "torna su" sarebbe solo un pulsante che dice l’ovvio.

Continua. La soglia è il 35% della pagina: è lì che tornare in cima smette di essere un gesto da una scrollata e diventa un viaggio. Solo allora il pulsante ha senso di esistere.

Eccolo: ora che sei abbastanza in basso, è comparso con una breve entrata. Non lampeggia, non rimbalza — sale in posizione e si ferma, come si conviene a uno strumento, non a una notifica.

Quando risali sopra la soglia se ne va, e più in fretta di quanto sia arrivato: le cose escono di scena più rapide di come entrano. È la stessa coerenza fisica di un oggetto che si toglie di mezzo.

Premilo e la pagina risale con uno scorrimento fluido — un salto netto, invece, se hai chiesto meno movimento. In entrambi i casi finisci dove volevi: in cima.

Questo è l’ultimo paragrafo, abbastanza in basso da rendere il pulsante davvero utile. Provalo: l’unico modo onesto di mostrare un "torna su" è darti una pagina da cui valga la pena tornare.

Torna su · appare dopo una soglia di scroll

Scorri verso il basso dentro la finestra: all’inizio, in basso a destra, non c’è niente. Il pulsante appare solo dopo il 35% di scroll, la soglia oltre la quale risalire smette di essere una scrollata e diventa un tragitto. Comparire prima sarebbe rumore — un pulsante che dice l’ovvio; comparire dopo è un servizio. E l’apparizione rispetta la legge del capitolo 01: entra in posizione in circa 220 ms, e quando risali sopra la soglia se ne va più in fretta di come è arrivato, perché le cose escono di scena più rapide di come entrano.

È un vero <button> con etichetta accessibile, e quando è invisibile viene tolto dal flusso con hidden: così non lo incontri con Tab quando non serve, e ricompare nella tab-order solo da visibile. Il click riporta in cima con scroll fluido — salto netto, di nuovo, sotto prefers-reduced-motion — e poi sposta il focus sul contenuto, non su un pulsante che sta già sparendo. Tutto dentro un finto contenitore scrollabile, perché la demo non muova la pagina vera: il «torna su» onesto è quello che ha davvero una pagina da cui valga la pena tornare.

Il segnaposto che non finge progresso

L’ultimo compagno è il più delicato sul piano dell’onestà. Chi legge dieci minuti a volte se ne va e torna: un segnaposto gli restituisce il punto. Ma deve restituire una posizione, non spacciare un progresso.

15.e

Il nastro fra le pagine

Un segnaposto di carta non bara: non ti dice che hai capito metà libro, ti dice solo a che pagina eri. Questo fa lo stesso. Salva la posizione, non un punteggio.

Scorri un po’ e premi "Metti il segnaposto qui". Da quel momento il browser ricorda l’altezza esatta a cui eri — non in continuazione, ma quando lo decidi tu o quando lasci la pagina.

Alla riapertura non riparte da solo: comparirebbe arrogante. Ti offre di riprendere, e basta. Tornare al punto è una tua scelta, non un automatismo che ti scippa il controllo dello scroll.

La differenza con una barra di progresso è sottile ma decisiva: la barra dice "quanto manca", il segnaposto dice "dove sei rimasto". Il primo è una misura, il secondo è una memoria.

Se il browser nega la memoria — modalità privata, storage pieno, permessi — il componente lo dice chiaro invece di fingere. Un segnaposto che mente sarebbe peggio di nessun segnaposto.

Sei in fondo. Metti il segnaposto qui, ricarica la pagina con la mente: lo ritroverai ad aspettarti, esattamente dove l’avevi lasciato. Né un pixel più avanti, né uno indietro.

Scorri un po’, poi metti il segnaposto dove sei.

Segnaposto · salva in localStorage, onesto su dove sei rimasto

Scorri un po’, premi «Metti il segnaposto qui»: il browser ricorda in localStorage l’altezza esatta a cui eri — non in continuazione, ma quando lo decidi tu o quando lasci la pagina. Alla riapertura non riparte da solo: comparirebbe arrogante, ti scippa lo scroll. Ti offre di riprendere, con un banner che dice «ti eri fermato qui, circa al N%», e lascia a te la scelta fra tornarci e ricominciare. Il ripristino è uno scroll fluido, salto netto sotto reduced motion.

Qui l’onestà è tutta nella differenza fra posizione e progresso. Una barra dice «quanto manca»; un segnaposto dice «dove sei rimasto» — il primo è una misura, il secondo è una memoria. Per questo non scrive mai «67% completato» come se avessi capito quel 67%: mostra dove eri, non un voto di avanzamento. È un nastro fra le pagine, non una pagella. E quando il browser nega la memoria — modalità privata, storage pieno, permessi negati — il componente lo dichiara con franchezza invece di fingere: un segnaposto che mente sarebbe peggio di nessun segnaposto.


Cinque compagni, un’unica disciplina: accompagnare senza mettersi davanti. L’indice che dice «sei qui», la barra che dice «quanto manca», la nota che non ti sposta, il pulsante che compare solo se serve, il segnaposto che ricorda dove eri senza fingere quanto hai capito. Nessuno di loro è il protagonista — il protagonista è il testo, e dieci minuti di attenzione che merita rispetto. Tenere compagnia a chi legge a lungo non è riempire i margini di gadget: è togliere ogni piccolo attrito del «dove sono, quanto manca, come torno» così in silenzio che il lettore non se ne accorge, e può restare altrove con la mente, dentro le parole.

Il prossimo capitolo resta sulla pagina lunga ma cambia sguardo: dall’accompagnare il lettore al comporre lo spazio in cui si muove. La griglia editoriale — cosa rende una pagina elegante prima ancora di essere bella?