Scroll odbija się na twoich stronach internetowych

Opublikowany: 2022-03-10
Krótkie podsumowanie ↬ W tym artykule opisano efekt odbijania się przewijania i sposób jego działania w różnych przeglądarkach internetowych. Zawiera recenzje kilku różnych rozwiązań sugerowanych w Internecie, które można wykorzystać do zapobiegania odbijaniu się przewijania. W tym artykule opisano również właściwość CSS overscroll-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.

Więcej po skoku! Kontynuuj czytanie poniżej ↓

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:

Przewijanie podskakujące w Firefoksie na macOS
Przewijanie podskakuje w Firefoksie na macOS. (duży podgląd)

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:

Przewijanie podskakujące w Chrome na macOS
Przewijanie podskakujące w Chrome na macOS. (duży podgląd)

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.

Przewijanie podskakując w Safari na macOS. Podobny efekt można zaobserwować w Edge i Safari na iOS
Przewijanie podskakując w Safari na macOS. Podobny efekt widać w Edge i Safari na iOS. (duży podgląd)

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:

Pozycjonowanie bezwzględne i względne
Pozycjonowanie bezwzględne i względne.

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:

Brakująca stopka w macOS Safari
Brak stopki w macOS Safari. (duży podgląd)

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ą:

Krótsza stopka w iOS Safari
Krótsza stopka w Safari na iOS.

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.