Défilement rebondissant sur vos sites Web
Publié: 2022-03-10overscroll-behavior
, qui a été implémentée dans Chrome en décembre 2017 et dans Firefox en mars 2018, est également décrite dans cet article. Une bonne compréhension de cet effet est très utile pour créer ou concevoir un site Web comportant des éléments fixes.Le rebond de défilement (également parfois appelé défilement 'élastique' ou 'défilement élastique') est souvent utilisé pour désigner l'effet que vous voyez lorsque vous faites défiler vers le haut d'une page ou d'un élément HTML, ou vers le bas de une page ou un élément, sur un appareil utilisant un écran tactile ou un trackpad, et un espace vide peut être vu pendant un moment avant que l'élément ou la page ne ressorte et ne s'aligne sur son haut/bas (lorsque vous relâchez votre toucher/doigts). Vous pouvez voir un effet similaire se produire dans le défilement CSS entre les éléments.
Cependant, cet article se concentre sur le rebond de défilement lorsque vous faites défiler vers le haut ou le bas d'une page Web. En d'autres termes, lorsque le scrollport a atteint sa limite de défilement.
Collecter des données, la manière puissante
Saviez-vous que CSS peut être utilisé pour collecter des statistiques ? En effet, il existe même une approche CSS uniquement pour suivre les interactions de l'interface utilisateur à l'aide de Google Analytics. Lire un article connexe →
Une bonne compréhension du rebond de défilement est très utile car elle vous aidera à décider comment vous construisez vos sites Web et comment vous voulez que la page défile.
Le rebond de défilement n'est pas souhaitable si vous ne voulez pas voir d'éléments fixed
lors d'un déplacement de page. Voici quelques exemples : lorsque vous souhaitez qu'un en-tête ou un pied de page soit fixé dans une certaine position, ou si vous souhaitez que tout autre élément tel qu'un menu soit fixe, ou si vous souhaitez que la page défile à certaines positions lors du défilement et vous ne voulez pas qu'un défilement supplémentaire se produise tout en haut ou en bas de la page, ce qui perturbera les visiteurs de votre site Web. Cet article proposera quelques solutions aux problèmes rencontrés lorsqu'il s'agit de faire rebondir le défilement tout en haut ou en bas d'une page Web.
Ma première rencontre avec l'effet
J'ai remarqué cet effet pour la première fois lorsque je mettais à jour un site Web que j'avais créé il y a longtemps. Vous pouvez consulter le site Web ici. Le pied de page en bas de page était censé être fixe dans sa position en bas de page et ne pas bouger du tout. En même temps, vous étiez censé pouvoir faire défiler de haut en bas le contenu principal de la page. Idéalement, cela fonctionnerait comme ceci :

Cela fonctionne actuellement de cette façon dans Firefox ou sur n'importe quel navigateur sur un appareil sans écran tactile ni trackpad. Cependant, à cette époque, j'utilisais Chrome sur un MacBook. Je défilais vers le bas de la page à l'aide d'un trackpad lorsque j'ai découvert que mon site Web ne fonctionnait pas correctement. Vous pouvez voir ce qui s'est passé ici :

Oh non! Ce n'était pas ce qui devait arriver ! J'avais défini la position du pied de page pour qu'elle soit au bas de la page en définissant sa propriété de position
CSS pour qu'elle ait une valeur de fixed
. C'est aussi un bon moment pour revoir quelle position: fixed;
est. Selon la spécification CSS 2.1, lorsqu'une "boîte" (dans ce cas, le pied de page bleu foncé) est fixe, elle est "fixe par rapport à la fenêtre d'affichage et ne bouge pas lors du défilement". Cela signifie que le pied de page n'était pas censé bouger lorsque vous faites défiler la page de haut en bas. C'est ce qui m'a inquiété quand j'ai vu ce qui se passait sur Chrome.
Pour rendre cet article plus complet, je vais vous montrer ci-dessous comment la page défile à la fois sur Mobile Edge, Mobile Safari et Desktop Safari. Ceci est différent de ce qui se passe lors du défilement sur Firefox et Chrome. J'espère que cela vous donne une meilleure compréhension de la façon dont exactement le même code fonctionne actuellement de différentes manières. Il est actuellement difficile de développer un défilement qui fonctionne de la même manière sur différents navigateurs Web.

À la recherche d'une solution
Une de mes premières pensées était qu'il y aurait un moyen simple et rapide de résoudre ce problème sur tous les navigateurs. Cela signifie que je pensais pouvoir trouver une solution qui prendrait quelques lignes de code CSS et qu'aucun JavaScript ne serait impliqué. Par conséquent, l'une des premières choses que j'ai faites a été d'essayer d'y parvenir. Les navigateurs que j'ai utilisés pour les tests comprenaient Chrome, Firefox et Safari sur macOS et Windows 10, et Edge et Safari sur iOS. Les versions de ces navigateurs étaient les plus récentes au moment de la rédaction de cet article (2018).
Solutions HTML et CSS uniquement
Positionnement absolu et relatif
L'une des premières choses que j'ai essayées a été d'utiliser le positionnement absolu et relatif pour positionner le pied de page, car j'avais l'habitude de créer des pieds de page comme celui-ci. L'idée serait de définir ma page Web à 100% de hauteur afin que le pied de page soit toujours en bas de la page avec une hauteur fixe, tandis que le contenu occupe 100% moins la hauteur du pied de page et vous pouvez faire défiler cela. Alternativement, vous pouvez définir un padding-bottom
au lieu d'utiliser calc
et définir la hauteur du body-container
à 100 % afin que le contenu de l'application ne chevauche pas le pied de page. Le code CSS ressemblait à ceci :
html { width: 100%; height: 100%; overflow: hidden; position: relative; } body { width: 100%; margin: 0; font-family: sans-serif; height: 100%; overflow: hidden; } .body-container { height: calc(100% - 100px); overflow: auto; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: absolute; bottom: 0; height: 100px; width: 100%; }
Cette solution fonctionne presque de la même manière que la solution d'origine (qui était juste position: fixed;
). Un avantage de cette solution par rapport à cela est que le défilement n'est pas pour la page entière, mais uniquement pour le contenu de la page sans le pied de page. Le plus gros problème avec cette méthode est que sur Mobile Safari, le pied de page et le contenu de l'application se déplacent en même temps. Cela rend cette approche très problématique lors d'un défilement rapide :

Un autre effet que je ne voulais pas était difficile à remarquer au début, et je n'ai réalisé qu'il se produisait qu'après avoir essayé plus de solutions. C'était qu'il était légèrement plus lent de faire défiler le contenu de mon application. Étant donné que nous définissons la hauteur de notre conteneur de défilement à 100 % de lui-même, cela entrave le défilement basé sur le mouvement/momentum sur iOS. Si cette hauteur de 100 % est plus courte (par exemple, lorsqu'une hauteur de 100 % de 2000 px devient une hauteur de 100 % de 900 px), le défilement basé sur l'élan s'aggrave. Le défilement basé sur le mouvement/momentum se produit lorsque vous effleurez la surface d'un écran tactile avec vos doigts et que la page défile d'elle-même. Dans mon cas, je voulais que le défilement basé sur l'élan se produise afin que les utilisateurs puissent faire défiler rapidement, donc je suis resté à l'écart des solutions qui définissent une hauteur de 100 %.

Autres tentatives
Une des solutions proposées sur le web, et que j'ai essayé d'utiliser sur mon code, est présentée ci-dessous à titre d'exemple.
html { width: 100%; position: fixed; overflow: hidden; } body { width: 100%; margin: 0; font-family: sans-serif; position: fixed; overflow: hidden; } .body-container { width: 100vw; height: calc(100vh - 100px); overflow-y: auto; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: fixed; bottom: 0; height: 100px; width: 100%; }
Ce code fonctionne sur Chrome et Firefox sur macOS de la même manière que la solution précédente. Un avantage de cette méthode est que le défilement n'est pas limité à une hauteur de 100 %, de sorte que le défilement basé sur l'élan fonctionne correctement. Sur Safari, cependant, le pied de page disparaît :

Sur iOS Safari, le pied de page devient plus court et il y a un espace supplémentaire transparent (ou blanc) en bas. De plus, la possibilité de faire défiler la page est perdue après avoir fait défiler vers le bas. Vous pouvez voir l'espace blanc sous le pied de page ici :

Une ligne de code intéressante que vous pourriez voir souvent est : -webkit-overflow-scrolling: touch;
. L'idée derrière cela est qu'il permet un défilement basé sur l'élan pour un élément donné. Cette propriété est décrite comme "non standard" et comme "pas sur une piste standard" dans la documentation MDN. Il apparaît comme une "valeur de propriété non valide" en cours d'inspection dans Firefox et Chrome, et il n'apparaît pas comme une propriété sur Desktop Safari. Je n'ai pas utilisé cette propriété CSS à la fin.
Pour montrer un autre exemple de solution que vous pouvez rencontrer et un résultat différent que j'ai trouvé, j'ai également essayé le code ci-dessous :
html { position: fixed; height: 100%; overflow: hidden; } body { font-family: sans-serif; margin: 0; width: 100vw; height: 100vh; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 110px; } footer { position: fixed; }
Cela fonctionne bien sur les différents navigateurs de bureau, le défilement basé sur l'élan fonctionne toujours et le pied de page est fixé en bas et ne bouge pas sur les navigateurs Web de bureau. La partie la plus problématique de cette solution (et ce qui la rend unique) est peut-être que, sur iOS Safari, le pied de page tremble et se déforme toujours très légèrement et vous pouvez voir le contenu en dessous chaque fois que vous faites défiler.
Solutions avec JavaScript
Après avoir essayé quelques solutions initiales en utilisant uniquement HTML et CSS, j'ai essayé quelques solutions JavaScript. Je voudrais ajouter que c'est quelque chose que je ne vous recommande pas de faire et qu'il vaut mieux éviter de faire. D'après mon expérience, il existe généralement des solutions plus élégantes et concises utilisant uniquement HTML et CSS. Cependant, j'avais déjà passé beaucoup de temps à essayer les autres solutions, je me suis dit que ça ne ferait pas de mal de voir rapidement s'il y avait des solutions alternatives qui utilisaient JavaScript.
Événements tactiles
Une approche pour résoudre le problème du rebond du défilement consiste à empêcher les événements touchmove
ou touchstart
sur la window
ou le document
. L'idée derrière cela est que les événements tactiles sur la fenêtre globale sont empêchés, tandis que les événements tactiles sur le contenu que vous souhaitez faire défiler sont autorisés. Un exemple de code comme celui-ci est illustré ci-dessous :
// Prevents window from moving on touch on older browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, false) // Allows content to move on touch. document.querySelector('.body-container').addEventListener('touchmove', function (event) { event.stopPropagation() }, false)
J'ai essayé de nombreuses variantes de ce code pour essayer de faire fonctionner correctement le défilement. Empêcher le touchmove
sur la window
n'a fait aucune différence. L'utilisation document
n'a fait aucune différence. J'ai également essayé d'utiliser à la fois touchstart
et touchmove
pour contrôler le défilement, mais ces deux méthodes n'ont également fait aucune différence. J'ai appris que vous ne pouvez plus appeler event.preventDefault()
de cette façon pour des raisons de performances. Vous devez définir l'option passive
sur false
dans l'écouteur d'événement :
// Prevents window from moving on touch on newer browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, {passive: false})
Bibliothèques
Vous pouvez rencontrer une bibliothèque appelée "iNoBounce" qui a été conçue pour "empêcher votre application Web iOS de rebondir lors du défilement". Une chose à noter lorsque vous utilisez cette bibliothèque en ce moment pour résoudre le problème que j'ai décrit dans cet article est qu'elle nécessite que vous -webkit-overflow-scrolling
. Une autre chose à noter est que la solution la plus concise avec laquelle j'ai fini (qui est décrite plus loin) fait la même chose que sur iOS. Vous pouvez le tester vous-même en regardant les exemples dans son référentiel GitHub et en le comparant à la solution avec laquelle je me suis retrouvé.
Comportement de survol
Après avoir essayé toutes ces solutions, j'ai découvert la propriété CSS overscroll-behavior
. La propriété CSS overscroll-behavior
a été implémentée dans Chrome 63 en décembre 2017 et dans Firefox 59 en mars 2018. Cette propriété, comme décrit dans la documentation MDN, « vous permet de contrôler le comportement de dépassement de défilement du navigateur — ce qui se passe lorsque la limite d'un la zone de défilement est atteinte. C'est la solution que j'ai fini par utiliser.
Tout ce que j'avais à faire était de définir overscroll-behavior
sur none
dans le body
de mon site Web et je pouvais laisser la position
du pied de page fixed
. Même si le défilement basé sur l'élan s'appliquait à toute la page, plutôt qu'au contenu sans le pied de page, cette solution était assez bonne pour moi et remplissait toutes mes exigences à ce moment-là, et mon pied de page ne rebondissait plus de manière inattendue sur Chrome. Il est peut-être utile de noter qu'Edge a cette propriété signalée comme étant en cours de développement. overscroll-behavior
peut être considéré comme une amélioration si les navigateurs ne le supportent pas encore.
Conclusion
Si vous ne voulez pas que vos en-têtes ou pieds de page fixes rebondissent sur vos pages Web, vous pouvez désormais utiliser la propriété CSS overscroll-behavior
.
Malgré le fait que cette solution fonctionne différemment dans différents navigateurs (le rebond du contenu de la page se produit toujours sur Safari et Edge, alors que sur Firefox et Chrome ce n'est pas le cas), il gardera l'en-tête ou le pied de page fixe lorsque vous faites défiler vers le haut ou en bas d'un site Web. C'est une solution concise et sur tous les navigateurs testés, le défilement basé sur l'élan fonctionne toujours, vous pouvez donc faire défiler très rapidement de nombreux contenus de page. Si vous créez un en-tête ou un pied de page fixe sur votre page Web, vous pouvez commencer à utiliser cette solution.