Supprimez vos fonctions de délai avant expiration et débarrassez-vous de leurs bugs. Voici l'événement dont vous avez vraiment besoin : "scrollend".
Avant l'événement scrollend
, il n'existait aucun moyen fiable de détecter qu'un défilement était terminé. Cela signifiait que les événements se déclenchaient tardivement ou alors que le doigt de l'utilisateur était toujours sur l'écran. Cette imprécision pour savoir quand le défilement a réellement pris fin a entraîné des bugs et une mauvaise expérience pour l'utilisateur.
document.onscroll = event => { clearTimeout(window.scrollEndTimer) window.scrollEndTimer = setTimeout(callback, 100) }
Le mieux que cette stratégie setTimeout()
puisse faire est de savoir si le défilement s'est arrêté pour 100ms
. Il s'agit donc plus d'un événement de défilement mis en pause que d'un événement de défilement terminé.
Après l'événement scrollend
, le navigateur effectue toutes ces évaluations difficiles à votre place.
document.onscrollend = event => {…}
C'est bien. Ils sont parfaitement synchronisés et remplis de conditions pertinentes avant d'être émis.
Essayer
Détails de l'événement
L'événement scrollend
se déclenche lorsque :
- Le navigateur n'anime plus ni ne traduit plus le défilement.
- Le contact de l'utilisateur a été relâché.
- Le pointeur de l'utilisateur a relâché le curseur de défilement.
- La touche de l'utilisateur a été relâchée.
- Le défilement jusqu'au fragment est terminé.
- L'ancrage de défilement est terminé.
- scrollTo()
est terminée.
- L'utilisateur a fait défiler la fenêtre d'affichage visuelle.
L'événement scrollend
ne se déclenche pas dans les cas suivants :
- Le geste d'un utilisateur n'a pas entraîné de modification de la position de défilement (aucune traduction n'a été effectuée).
- scrollTo()
n'a généré aucune traduction.
La raison pour laquelle cet événement a mis si longtemps à arriver sur la plate-forme Web est due aux nombreux petits détails qui nécessitaient des spécifications détaillées. L'un des aspects les plus complexes a été d'articuler les détails scrollend
pour le Visual Viewport par rapport au document. Imaginons une page Web sur laquelle vous faites un zoom avant. Vous pouvez faire défiler l'écran dans cet état de zoom, mais cela ne fait pas nécessairement défiler le document. Sachez que même cette interaction de défilement visuelle pilotée par l'utilisateur émettra l'événement scrollend
une fois terminée.
Utiliser l'événement
Comme pour les autres événements de défilement, vous pouvez enregistrer des écouteurs de plusieurs manières.
addEventListener("scrollend", (event) => {
// scroll ended
});
aScrollingElement.addEventListener("scrollend", (event) => {
// scroll ended
});
Vous pouvez également utiliser la propriété d'événement:
document.onscrollend = (event) => {
// scroll ended
};
aScrollingElement.onscrollend = (event) => {
// scroll ended
};
Polyfills et amélioration progressive
Si vous souhaitez utiliser ce nouvel événement dès maintenant, voici nos meilleurs conseils. Vous pouvez continuer à utiliser votre stratégie de fin de défilement actuelle (si vous en avez une) et au début, vérifier la compatibilité avec:
'onscrollend' in window
// true, if available
La valeur renvoyée sera "true" ou "false" selon que le navigateur propose l'événement. Avec cette vérification, vous pouvez créer une branche de code:
if ('onscrollend' in window) {
document.onscrollend = callback
}
else {
document.onscroll = event => {
clearTimeout(window.scrollEndTimer)
window.scrollEndTimer = setTimeout(callback, 100)
}
}
C'est un bon début pour améliorer progressivement votre événement scrollend
lorsqu'il sera disponible. Vous pouvez également essayer un polyfill (NPM) que j'ai créé pour que le navigateur fonctionne au mieux:
import {scrollend} from "scrollyfills"
// then use scrollend as if it's existed this whole time
document.onscrollend = callback
Le polyfill s'améliorera progressivement pour utiliser l'événement scrollend
intégré au navigateur, le cas échéant. Si elle n'est pas disponible, le script surveille les événements de pointeur et le défilement pour obtenir la meilleure estimation possible de la fin de l'événement.
Cas d'utilisation
Il est recommandé d'éviter les tâches de calcul lourdes pendant le défilement. Cette pratique garantit que le défilement peut utiliser autant de mémoire et de traitement que possible pour assurer une expérience fluide. L'utilisation d'un événement scrollend
est le moment idéal pour appeler et effectuer le travail difficile, car le défilement ne se produit plus.
L'événement scrollend
peut être utilisé pour déclencher différentes actions. Un cas d'utilisation courant consiste à synchroniser les éléments d'interface utilisateur associés avec la position à laquelle le défilement s'est arrêté. Par exemple :
- Synchronisation de la position de défilement d'un carrousel avec un indicateur en forme de point.
- Synchroniser un élément de galerie avec ses métadonnées.
- Récupération de données après qu'un utilisateur a fait défiler un nouvel onglet.
Imaginons qu'un utilisateur balaie un e-mail. Une fois le balayage terminé, vous pouvez effectuer l'action en fonction de l'endroit où l'utilisateur a fait défiler l'écran.
Vous pouvez également utiliser cet événement pour la synchronisation après un défilement programmatique ou utilisateur, ou pour des actions telles que la journalisation des données analytiques.
Voici un bon exemple où plusieurs éléments tels que les flèches, les points et la sélection doivent être mis à jour en fonction de la position de défilement. Découvrez comment j'ai créé ce carrousel sur YouTube. Vous pouvez également essayer la démo en direct.
Merci à Mehdi Kazemi pour son travail d'ingénierie et à Robert Flack pour ses conseils sur l'API et l'implémentation.