Scroll odbija się na twoich stronach internetowych
Opublikowany: 2022-03-10overscroll-behavior
, która została zaimplementowana w przeglądarce Chrome w grudniu 2017 r. i w przeglądarce Firefox w marcu 2018 r. Dobre zrozumienie tego efektu jest bardzo pomocne przy tworzeniu lub projektowaniu dowolnej strony internetowej, która ma stałe elementy.Przewijanie przewijania (czasem określane także jako „gumowanie” lub „elastyczne przewijanie”) jest często używane w odniesieniu do efektu, który widzisz, gdy przewijasz do samej góry strony lub elementu HTML, albo do dołu stronę lub element na urządzeniu korzystającym z ekranu dotykowego lub gładzika, a puste miejsce może być widoczne przez chwilę, zanim element lub strona odskoczy i wyrówna się z powrotem do góry / dołu (po zwolnieniu dotyku / palców). Podobny efekt można zaobserwować w przypadku przewijania CSS między elementami.
Jednak ten artykuł koncentruje się na odbijaniu przewijania podczas przewijania do samej góry lub na sam dół strony internetowej. Innymi słowy, gdy port przewijania osiągnął granicę przewijania.
Zbieranie danych, potężny sposób
Czy wiesz, że CSS można wykorzystać do zbierania statystyk? Rzeczywiście, istnieje nawet podejście oparte wyłącznie na CSS do śledzenia interakcji interfejsu użytkownika za pomocą Google Analytics. Przeczytaj powiązany artykuł →
Dobre zrozumienie odbijania przewijania jest bardzo przydatne, ponieważ pomoże Ci zdecydować, w jaki sposób tworzysz swoje witryny i jak chcesz, aby strona się przewijała.
Odbijanie przewijania jest niepożądane, jeśli nie chcesz widzieć fixed
elementów w ruchu strony. Oto kilka przykładów: gdy chcesz, aby nagłówek lub stopka były ustalone w określonej pozycji, lub jeśli chcesz, aby jakikolwiek inny element, taki jak menu, został naprawiony, lub jeśli chcesz, aby strona przewijała się-przyciągała w określonych pozycjach podczas przewijania i nie chcesz, aby dodatkowe przewijanie pojawiało się na samej górze lub na dole strony, co zdezorientuje odwiedzających Twoją witrynę. W tym artykule zaproponujemy kilka rozwiązań problemów napotykanych podczas odbijania się przewijania na samej górze lub na dole strony internetowej.
Moje pierwsze spotkanie z efektem
Po raz pierwszy zauważyłem ten efekt podczas aktualizacji strony internetowej, którą zbudowałem dawno temu. Stronę internetową można obejrzeć tutaj. Stopka na dole strony miała być unieruchomiona w swoim położeniu na dole strony iw ogóle się nie przesuwać. Jednocześnie miałeś mieć możliwość przewijania w górę iw dół głównej zawartości strony. Idealnie działałoby to tak:
Obecnie działa w ten sposób w Firefoksie lub w dowolnej przeglądarce na urządzeniu bez ekranu dotykowego lub gładzika. Jednak w tym czasie korzystałem z Chrome na MacBooku. Przewijałem do dołu strony za pomocą gładzika, kiedy odkryłem, że moja witryna nie działa poprawnie. Tutaj możesz zobaczyć, co się stało:
O nie! Nie tak miało się stać! Ustawiłem pozycję stopki na dole strony, ustawiając jej właściwość CSS position
na wartość fixed
. Jest to również dobry moment, aby ponownie przyjrzeć się, jaką position: fixed;
jest. Zgodnie ze specyfikacją CSS 2.1, gdy „pudełko” (w tym przypadku ciemnoniebieska stopka) jest stałe, jest „stałe w stosunku do widocznego obszaru i nie porusza się podczas przewijania”. Oznacza to, że stopka nie powinna się poruszać podczas przewijania strony w górę iw dół. To właśnie mnie zmartwiło, gdy zobaczyłem, co się dzieje w Chrome.
Aby uzupełnić ten artykuł, pokażę poniżej, jak strona przewija się w Mobile Edge, Mobile Safari i Desktop Safari. Różni się to od tego, co dzieje się podczas przewijania w Firefoksie i Chrome. Mam nadzieję, że pozwoli to lepiej zrozumieć, w jaki sposób ten sam kod działa obecnie na różne sposoby. Obecnie wyzwaniem jest opracowanie przewijania, które działa w ten sam sposób w różnych przeglądarkach internetowych.
Poszukiwanie rozwiązania
Jedną z moich pierwszych myśli było to, że będzie łatwy i szybki sposób na naprawienie tego problemu we wszystkich przeglądarkach. Oznacza to, że pomyślałem, że znajdę rozwiązanie, które zajmie kilka linijek kodu CSS i nie będzie zaangażowany żaden JavaScript. Dlatego jedną z pierwszych rzeczy, które zrobiłem, była próba osiągnięcia tego celu. Przeglądarki, których użyłem do testowania, to Chrome, Firefox i Safari na macOS i Windows 10 oraz Edge i Safari na iOS. Wersje tych przeglądarek były najnowsze w momencie pisania tego artykułu (2018).
Tylko rozwiązania HTML i CSS
Pozycjonowanie bezwzględne i względne
Jedną z pierwszych rzeczy, które spróbowałem, było użycie pozycjonowania bezwzględnego i względnego do pozycjonowania stopki, ponieważ byłem przyzwyczajony do budowania takich stopek. Pomysł polegałby na ustawieniu mojej strony internetowej na 100% wysokości, tak aby stopka była zawsze na dole strony ze stałą wysokością, podczas gdy treść zajmowała 100% minus wysokość stopki i można ją przewijać. Alternatywnie możesz ustawić padding-bottom
zamiast calc
i ustawić wysokość body-container
na 100%, aby zawartość aplikacji nie pokrywała się ze stopką. Kod CSS wyglądał mniej więcej tak:
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%; }
To rozwiązanie działa prawie tak samo jak oryginalne rozwiązanie (które było właśnie position: fixed;
). Jedną z zalet tego rozwiązania w porównaniu z tym jest to, że przewijanie nie dotyczy całej strony, ale tylko zawartości strony bez stopki. Największym problemem związanym z tą metodą jest to, że w Mobile Safari zarówno stopka, jak i zawartość aplikacji poruszają się w tym samym czasie. To sprawia, że takie podejście jest bardzo problematyczne przy szybkim przewijaniu:
Inny efekt, którego nie chciałem, był początkowo trudny do zauważenia, a dopiero po wypróbowaniu kolejnych rozwiązań zorientowałem się, że to się dzieje. Chodziło o to, że przewijanie zawartości mojej aplikacji było nieco wolniejsze. Ponieważ ustawiamy wysokość kontenera przewijania na 100% samego siebie, utrudnia to przewijanie oparte na ruchu/momentum w systemie iOS. Jeśli ta 100% wysokość jest krótsza (na przykład, gdy 100% wysokość 2000 pikseli staje się 100% wysokością 900 pikseli), przewijanie oparte na pędzie pogorszy się. Przewijanie oparte na szybkim ruchu/momentum ma miejsce, gdy przesuniesz palcami powierzchnię ekranu dotykowego, a strona sama się przewinie. W moim przypadku chciałem, aby przewijanie oparte na pędzie było możliwe, aby użytkownicy mogli szybko przewijać, więc trzymałem się z dala od rozwiązań, które ustawiają wysokość na 100%.
Inne próby
Jedno z rozwiązań sugerowanych w sieci, które próbowałem zastosować w swoim kodzie, pokazano poniżej jako przykład.
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%; }
Ten kod działa w przeglądarkach Chrome i Firefox na macOS w taki sam sposób, jak poprzednie rozwiązanie. Zaletą tej metody jest to, że przewijanie nie jest ograniczone do 100% wysokości, więc przewijanie oparte na pędzie działa prawidłowo. Jednak w Safari stopka znika:
W iOS Safari stopka staje się krótsza, a na dole znajduje się dodatkowa przezroczysta (lub biała) przerwa. Również możliwość przewijania strony jest tracona po przewinięciu na sam dół. Tutaj możesz zobaczyć białą przerwę pod stopką:
Jedna interesująca linia kodu, którą możesz często zobaczyć, to: -webkit-overflow-scrolling: touch;
. Ideą tego jest to, że umożliwia przewijanie oparte na pędzie dla danego elementu. Ta właściwość jest opisana jako „niestandardowa” i jako „nie na standardowym torze” w dokumentacji MDN. Pojawia się jako „Nieprawidłowa wartość właściwości” podczas sprawdzania w przeglądarkach Firefox i Chrome i nie pojawia się jako właściwość w przeglądarce Safari na komputerze. Ostatecznie nie użyłem tej właściwości CSS.
Aby pokazać inny przykład rozwiązania, które możesz napotkać i inny wynik, który znalazłem, wypróbowałem również poniższy kod:
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; }
Działa to dobrze w różnych przeglądarkach komputerowych, przewijanie oparte na tempie nadal działa, a stopka jest zamocowana na dole i nie porusza się w przeglądarkach internetowych na komputery stacjonarne. Być może najbardziej problematyczną częścią tego rozwiązania (i tym, co czyni je wyjątkowym) jest to, że w Safari na iOS stopka zawsze lekko się trzęsie i zniekształca, a zawartość pod nią widać przy każdym przewijaniu.
Rozwiązania z JavaScript
Po wypróbowaniu kilku początkowych rozwiązań przy użyciu tylko HTML i CSS, wypróbowałem kilka rozwiązań JavaScript. Dodam, że jest to coś, czego nie polecam i lepiej byłoby tego unikać. Z mojego doświadczenia wynika, że zwykle są bardziej eleganckie i zwięzłe rozwiązania wykorzystujące tylko HTML i CSS. Jednak spędziłem już dużo czasu na wypróbowaniu innych rozwiązań, pomyślałem, że nie zaszkodzi szybko sprawdzić, czy istnieją alternatywne rozwiązania wykorzystujące JavaScript.
Dotknij Wydarzenia
Jednym ze sposobów rozwiązania problemu odbijania się przewijania jest zapobieganie zdarzeniom touchmove
lub touchstart
w window
lub document
. Ideą tego jest zapobieganie zdarzeniom dotykowym w całym oknie, podczas gdy zdarzenia dotykowe w treści, którą chcesz przewijać, są dozwolone. Przykład takiego kodu pokazano poniżej:
// 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)
Próbowałem wielu odmian tego kodu, aby zwój działał poprawnie. Zapobieganie touchmove
w window
nie robiło żadnej różnicy. Korzystanie z document
nie miało znaczenia. Próbowałem również używać zarówno touchstart
, jak i touchmove
do kontrolowania przewijania, ale te dwie metody również nie robiły różnicy. Dowiedziałem się, że nie można już w ten sposób wywołać event.preventDefault()
ze względu na wydajność. Musisz ustawić opcję passive
na false
w detektorze zdarzeń:
// Prevents window from moving on touch on newer browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, {passive: false})
Biblioteki
Możesz natknąć się na bibliotekę o nazwie „iNoBounce”, która została stworzona, aby „zatrzymać podskakiwanie aplikacji internetowej na iOS podczas przewijania”. Jedną rzeczą, na którą należy zwrócić uwagę podczas korzystania z tej biblioteki w celu rozwiązania problemu, który opisałem w tym artykule, jest to, że wymaga ona użycia -webkit-overflow-scrolling
. Inną rzeczą, na którą należy zwrócić uwagę, jest to, że bardziej zwięzłe rozwiązanie, które znalazłem (opisane później), działa podobnie jak na iOS. Możesz to sam przetestować, patrząc na przykłady w repozytorium GitHub i porównując to z rozwiązaniem, które skończyłem.
Zachowanie podczas przewijania
Po wypróbowaniu wszystkich tych rozwiązań dowiedziałem się o właściwości CSS overscroll-behavior
. Właściwość CSS overscroll-behavior
została zaimplementowana w przeglądarce Chrome 63 w grudniu 2017 r., a w przeglądarce Firefox 59 w marcu 2018 r. Ta właściwość, jak opisano w dokumentacji MDN, „pozwala kontrolować zachowanie przepełnienia przewijania przeglądarki — co się dzieje, gdy granica obszar przewijania został osiągnięty.” To było rozwiązanie, którego ostatecznie użyłem.
Jedyne, co musiałem zrobić, to ustawić overscroll-behavior
na none
w body
mojej witryny i mogłem pozostawić fixed
position
stopki . Mimo że przewijanie oparte na tempie dotyczyło całej strony, a nie treści bez stopki, to rozwiązanie było dla mnie wystarczająco dobre i spełniało wszystkie moje wymagania w tamtym momencie, a stopka nie odbijała się już niespodziewanie w Chrome. Być może warto zauważyć, że Edge ma teraz oznaczenie tej właściwości jako w fazie rozwoju. overscroll-behavior
może być postrzegane jako ulepszenie, jeśli przeglądarki jeszcze go nie obsługują.
Wniosek
Jeśli nie chcesz, aby stałe nagłówki lub stopki odbijały się na Twoich stronach internetowych, możesz teraz użyć właściwości CSS overscroll-behavior
.
Pomimo tego, że to rozwiązanie działa różnie w różnych przeglądarkach (odbijanie zawartości strony nadal ma miejsce w Safari i Edge, podczas gdy w Firefox i Chrome tak nie jest), zachowa nagłówek lub stopkę na stałe podczas przewijania do samej góry lub na dole strony internetowej. Jest to zwięzłe rozwiązanie i we wszystkich testowanych przeglądarkach przewijanie oparte na tempie nadal działa, dzięki czemu możesz bardzo szybko przewijać wiele treści na stronie. Jeśli budujesz stały nagłówek lub stopkę na swojej stronie internetowej, możesz zacząć korzystać z tego rozwiązania.