Un indicateur de progression du défilement est un modèle d'interface utilisateur courant qui communique visuellement la progression de l'utilisateur dans un document ou un conteneur à défilement. À mesure que l'utilisateur fait défiler la page, un élément visuel s'actualise pour refléter sa position, ce qui lui permet de savoir clairement et intuitivement quelle quantité de contenu a été consultée et combien il en reste.
Mise en œuvre
Pour créer un indicateur de progression du défilement, vous avez besoin de deux éléments :
- Un élément qui servira de barre de progression. Cet élément est généralement
position: fixedouposition: absoluteafin qu'il reste visible lorsque l'utilisateur fait défiler la page. - Animation associée à la position de défilement.
Voici comment procéder :
- Commencez par créer un élément HTML qui servira de barre de progression. Vous pouvez personnaliser le style de cet élément selon vos préférences.
- Ensuite, dans votre CSS, définissez une animation
@keyframesqui met à l'échelle la barre de progression. Une approche courante consiste à mettre à l'échelle l'élément descaleX(0)àscaleX(1). - Enfin, appliquez cette animation à l'élément de la barre de progression et définissez sa propriété
animation-timelinesur une timeline de défilement. Cela indique au navigateur de piloter la progression de l'animation en fonction de la position de défilement du conteneur de défilement ancêtre le plus proche.
Exemple de code
Ce code agrandit l'élément #progress lors du défilement à l'aide d'une chronologie de défilement anonyme, créée par la fonction 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();
}
}
}
En raison de son emplacement dans le DOM, la fonction scroll() suivra le défilement de son ancêtre le plus proche dans la direction block, qui est ici le défilement racine.
<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>
Ce code agrandit l'élément #progress lors du défilement à l'aide d'une timeline de défilement nommée, créée par la propriété 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;
}
}
}
Bonnes pratiques
Lorsque vous utilisez des animations basées sur le défilement, il est important de suivre quelques bonnes pratiques pour garantir une expérience fluide et accessible :
- À FAIRE : incluez la détection de fonctionnalités. Tous les navigateurs ne sont pas compatibles avec les animations déclenchées par le défilement. Utilisez
@supports (animation-timeline: scroll())pour vérifier la compatibilité et fournir une solution de remplacement pour les navigateurs qui ne sont pas compatibles.- N'UTILISEZ PAS le package
scroll-timeline-polyfillpour la stratégie de remplacement, car il n'est pas complet et présente de nombreux problèmes connus. - Si l'animation n'est considérée que comme décorative, optez pour l'amélioration progressive et NE FOURNISSEZ PAS de solution de remplacement.
- N'UTILISEZ PAS le package
- À FAIRE : Supprimez les éléments purement décoratifs des flux de lecture des technologies d'assistance. Appliquez
aria-hidden="true"aux indicateurs de défilement purement visuels pour vous assurer que les lecteurs d'écran ne rencontrent pas de nœuds vides sans nom. - À FAIRE : Respectez les préférences des utilisateurs. Certains préfèrent avoir moins de mouvements sur le Web. Utilisez la requête média
prefers-reduced-motionpour désactiver ou réduire vos animations pour ces utilisateurs. - À FAIRE : Essayez de n'animer que les propriétés CSS performantes. Pour des animations plus fluides, n'animez que les propriétés pouvant être gérées par le thread du compositeur du navigateur, telles que
transformetopacity. L'animation d'autres propriétés telles quewidthouheightpeut entraîner des problèmes de performances. - À FAIRE : Utilisez l'ordre de déclaration correct. Lorsque vous utilisez la propriété abrégée
animation, déclarezanimation-timelineaprès celle-ci pour éviter que la propriété abrégée ne réinitialise la chronologie.
Lorsque vous utilisez la fonction scroll() pour créer une animation basée sur le défilement :
- FACULTATIF : soyez explicite concernant le conteneur de défilement. Lorsque vous ne ciblez pas le conteneur de défilement ancêtre le plus proche, indiquez explicitement celui que vous souhaitez utiliser avec
scroll(root)ouscroll(self).- Lorsque
root,nearestouselfne suffisent pas, utilisez une chronologie de défilement nommée.
- Lorsque
- FACULTATIF : indiquez explicitement l'axe à suivre. Lorsque vous ne ciblez pas l'axe
blockpar défaut (par exemple, dans un défilement horizontal), indiquez explicitement l'axe à suivre avecscroll(block)ouscroll(inline).
Lorsque vous utilisez la propriété scroll-timeline pour créer une animation basée sur le défilement :
- À FAIRE : utilisez une
<dashed-ident>CSS pour le nom. - FACULTATIF : Soyez explicite sur l'axe à suivre. Lorsque vous ne ciblez pas l'axe
blockpar défaut (par exemple, dans un défilement horizontal), indiquez explicitement l'axe à suivre avecscroll-timeline-axis. - À FAIRE : Assurez-vous que le champ d'application de la recherche fonctionne. Lorsque l'élément qui déclare
scroll-timelinen'est pas un ancêtre de l'arborescence plate de l'élément animé, augmentez la visibilité du nom descroll-timelineen utilisanttimeline-scopesur un ancêtre partagé.
Stratégies de remplacement
Pour les navigateurs qui ne sont pas compatibles avec les animations déclenchées par le défilement, vous pouvez utiliser une solution de remplacement pour recréer les effets visuels. Les solutions de remplacement sont généralement créées avec un écouteur de défilement (pour les effets ScrollTimeline) ou l'API IntersectionObserver (pour les effets ViewTimeline).
Dans les navigateurs compatibles de manière native avec les animations liées au défilement, utilisez TOUJOURS l'implémentation CSS native, car elle est plus performante.
Notez que tous les effets ne peuvent pas être recréés à l'aide de l'approche de remplacement.
Pour ce cas d'utilisation spécifique, le script suivant applique la solution de remplacement pour les navigateurs qui ne sont pas compatibles avec les animations déclenchées par le défilement. Il utilise un écouteur de défilement pour suivre la position de défilement de l'élément racine et met à jour la propriété transform de la barre de progression en conséquence.
<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>