Un indicatore di avanzamento dello scorrimento è un pattern di interfaccia utente comune che comunica visivamente l'avanzamento dell'utente in un documento o contenitore scorrevole. Mentre l'utente scorre, un elemento visivo si aggiorna per riflettere la sua posizione, fornendo un'idea chiara e intuitiva di quanti contenuti sono stati visualizzati e quanti ne rimangono.
Come implementare
Per creare un indicatore di avanzamento dello scorrimento, sono necessarie due cose:
- Un elemento che funge da barra di avanzamento. Questo elemento è in genere
position: fixedoposition: absolutein modo che rimanga visibile mentre l'utente scorre la pagina. - Un'animazione collegata alla posizione di scorrimento.
Ecco come fare:
- Innanzitutto, crea un elemento HTML che fungerà da barra di avanzamento. Questo elemento può essere personalizzato a tuo piacimento.
- Poi, nel CSS, definisci un'animazione
@keyframesche ridimensiona la barra di avanzamento. Un approccio comune consiste nello scalare l'elemento dascaleX(0)ascaleX(1). - Infine, applica questa animazione all'elemento della barra di avanzamento e imposta la proprietà
animation-timelinesu una cronologia di scorrimento. In questo modo, il browser viene istruito a gestire l'avanzamento dell'animazione in base alla posizione di scorrimento dello scroller predecessore più vicino.
Esempio di codice
Questo codice aumenta l'elemento #progress durante lo scorrimento utilizzando una cronologia di scorrimento anonima, creata dalla funzione scroll().
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: scroll())) {
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
#progress {
position: fixed;
left: 0; top: 0;
width: 100%; height: 1em;
background: red;
transform-origin: 0 50%;
animation: grow-progress auto linear;
animation-timeline: scroll();
}
}
}
A causa della sua posizione nel DOM, la funzione scroll() monitorerà lo scroller predecessore più vicino nella direzione block, che in questo caso è lo scroller principale.
<body>
<!-- MANDATORY: Purely decorative visual scroll progress bars MUST set aria-hidden="true" to remove the empty element from the assistive technology reading tree -->
<div id="progress" aria-hidden="true"></div>
</body>
Questo codice espande l'elemento #progress durante lo scorrimento utilizzando una cronologia di scorrimento denominata, creata dalla proprietà scroll-timeline.
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: scroll())) {
@keyframes grow-progress {
from { transform: scaleX(0); }
to { transform: scaleX(1); }
}
:root {
scroll-timeline: --tl block;
}
#progress {
position: fixed;
left: 0; top: 0;
width: 100%; height: 1em;
background: red;
transform-origin: 0 50%;
animation: grow-progress auto linear;
animation-timeline: --tl;
}
}
}
Best practice
Quando utilizzi le animazioni di scorrimento, è importante seguire alcune best practice per garantire un'esperienza fluida e accessibile:
- SÌ: includi il rilevamento delle funzionalità. Non tutti i browser supportano le animazioni basate sullo scorrimento. Utilizza
@supports (animation-timeline: scroll())per verificare il supporto e fornire un'alternativa per i browser che non lo supportano.- NON utilizzare il pacchetto
scroll-timeline-polyfillper la strategia di riserva, in quanto non è completo di funzionalità e presenta molti problemi noti. - Se l'animazione è considerata solo decorativa, opta per il potenziamento progressivo e NON fornire un fallback.
- NON utilizzare il pacchetto
- SÌ: rimuovi gli elementi puramente decorativi dai flussi di lettura delle tecnologie per la disabilità. Applica
aria-hidden="true"agli indicatori di scorrimento puramente visivi per assicurarti che gli screen reader non incontrino nodi vuoti e senza nome. - SÌ: rispetta le preferenze degli utenti. Alcuni utenti preferiscono un movimento ridotto sul web. Utilizza la query supporti
prefers-reduced-motionper disattivare o ridurre le animazioni per questi utenti. - SÌ: prova ad animare solo le proprietà CSS con prestazioni elevate. Per ottenere animazioni più fluide, limita l'animazione alle proprietà che possono essere gestite dal thread del compositore del browser, come
transformeopacity. L'animazione di altre proprietà comewidthoheightpuò causare problemi di prestazioni. - SÌ: utilizza l'ordine di dichiarazione corretto. Quando utilizzi la proprietà abbreviata
animation, dichiaraanimation-timelinedopo per evitare che la proprietà abbreviata reimposti la sequenza temporale.
Quando utilizzi la funzione scroll() per creare un'animazione basata sullo scorrimento:
- FACOLTATIVO Specifica lo scroller: se non scegli come target lo scroller dell'antenato più vicino, specifica lo scroller che vuoi utilizzare con
scroll(root)oscroll(self).- Quando
root,nearestoselfnon sono sufficienti, utilizza una cronologia di scorrimento con nome.
- Quando
- FACOLTATIVO Specifica l'asse da monitorare: se non scegli come target l'asse
blockpredefinito (ad esempio in uno scroller orizzontale), specifica l'asse da monitorare conscroll(block)oscroll(inline).
Quando utilizzi la proprietà scroll-timeline per creare un'animazione basata sullo scorrimento:
- SÌ: utilizza un CSS
<dashed-ident>per il nome. - FACOLTATIVO Specifica l'asse da monitorare: se non scegli come target l'asse
blockpredefinito (ad esempio in uno scroller orizzontale), specifica l'asse da monitorare conscroll-timeline-axis. - SÌ: assicurati che l'ambito della ricerca funzioni. Quando l'elemento che dichiara
scroll-timelinenon è un antenato dell'albero piatto dell'elemento animato, aumenta la visibilità del nome discroll-timelineutilizzandotimeline-scopesu un antenato condiviso.
Strategie di riserva
Per i browser che non supportano le animazioni basate sullo scorrimento, puoi utilizzare un comportamento di riserva per ricreare gli effetti visivi. I fallback vengono in genere creati con un listener di scorrimento (per gli effetti ScrollTimeline) o con l'API IntersectionObserver (per gli effetti ViewTimeline).
Nei browser con supporto integrato per le animazioni basate sullo scorrimento, utilizza SEMPRE l'implementazione CSS nativa, in quanto è più efficiente.
Tieni presente che non tutti gli effetti possono essere ricreati utilizzando l'approccio dei fallback.
Per questo caso d'uso specifico, lo script seguente applica il comportamento di riserva per i browser che non supportano le animazioni basate sullo scorrimento. Utilizza un listener di scorrimento per monitorare la posizione di scorrimento dell'elemento root e aggiorna di conseguenza la proprietà transform della barra di avanzamento.
<script>
if (!CSS.supports('animation-timeline', 'scroll()')) {
const progress = document.querySelector('#progress');
window.addEventListener('scroll', () => {
const scrollable = document.documentElement.scrollHeight - window.innerHeight;
const scrolled = window.scrollY;
const progressPercentage = (scrolled / scrollable);
progress.style.transform = `scaleX(${progressPercentage})`;
});
}
</script>