Имајте у виду да је овај блог пост објављен у јуну 2015. године, тако да у зависности од тога када га читате, одређени делови могу бити застарели. Нажалост, не могу увек да ажурирам ове постове како бих осигурао да информације остану тачне.
- Moja testna stranica
- Razumevanje podrazumevanog ponašanja
- Razumevanje šta radi CSS pravilo "-webkit-overflow-scrolling"
- Korisnik treba da sačeka dok se efekat elastičnog vraćanja završi
- Kako sprečiti da pozadinska stranica skroluje
- Kako sprečiti prekomerno skrolovanje na pozadinskoj stranici
- Kako sprečiti prelazak na pozadinsku stranicu prilikom skrolovanja preko kraja stranice
- Ceo izvorni kod stranice
Kako bih rešio nedavni problem sa skrolovanjem u Safariju na iOS-u, morao sam da napravim sopstvenu jednostavnu test-stranicu i zatim da primenim sve informacije i kombinacije koje sam mogao da nađem na internetu kako bih pokušao da rešim problem.
Evo kratkog pregleda onoga što sam otkrio tokom ovog procesa.
Moja testna stranica
Moja testna stranica bila je prilično jednostavna. Sastojala se od lažnih podataka u statičkom div-u koji predstavlja 'stranicu', uz fiksni div koji predstavlja preklopljeni 'meni' iznad stranice, kao što je ovo.
Kompletan izvorni kod stranice možete pronaći na dnu ovog blog posta.
Razumevanje podrazumevanog ponašanja
Prva stvar bila je da pokušam da razumem podrazumevano ponašanje Safarija na iOS-u. Najvažnije zapažanje bilo je da kada se skroluje do kraja menija, telo stranice pokazalo je 'efekat gumene trake' – ugrađena karakteristika Safarija.
Isto se desilo i kada sam skrolovao do samog vrha menija.
Međutim, prvi problem koji sam primetio jeste da, ako se neprekidno pomerate do samog vrha ili dna stranice, Safari počinje da prikazuje vizuelne greške u pozadini stranice i u meniju.
Nisam siguran zašto, ali pretpostavljam da ima veze sa funkcijom gumene trake.
Razumevanje šta radi CSS pravilo "-webkit-overflow-scrolling"
Sledeća stvar koju sam uradio bila je primena CSS pravila -webkit-overflow-scrolling na meniju, koje omogućava klizanje uz momentum.
Kao što je prikazano na slici ispod, skrolovanje se nastavlja čak i nakon što prevučem prstom po ekranu.
Ali takođe dodaje efekat gumene trake kada se skroluje do samog vrha ili dna stranice, kao što je prikazano ispod.
Korisnik treba da sačeka dok se efekat elastičnog vraćanja završi
Tokom testiranja primetio sam da, dok traje rubber-band efekat, korisnik ne može prebaciti fokus na drugi element sve dok animacija u potpunosti ne završi.
U donjem primeru, prvo skrolujem pozadinsku stranicu, a zatim brzo pokušavam da skrolujem meni, ali na kraju nastavim da skrolujem pozadinsku stranicu.
Međutim, ako sačekam trenutak da efekat završi, onda mogu početi da skrolujem kroz meni.
Kako sprečiti da pozadinska stranica skroluje
Tokom testiranja primetio sam i da, dok traje rubber-band efekat, korisnik ne može da premesti fokus na drugi element sve dok se animacija potpuno ne završi.
Na osnovu ovog odgovora sa Stack Overflow, možete osigurati da elementi sa disable-scrolling ne izvrše podrazumevanu akciju skrolovanja kada se pokrene događaj touchmove.
document.ontouchmove = function(event) {
var isTouchMoveAllowed = true,
target = event.target;
while (target !== null) {
if (target.classList && target.classList.contains('disable-scrolling')) {
isTouchMoveAllowed = false;
break;
}
target = target.parentNode;
}
if (!isTouchMoveAllowed) {
event.preventDefault();
}
};
Zatim primenite klasu disable-scrolling na div stranice:
<div class="page disable-scrolling">
Ovo nekako funkcioniše, ali detaljnija testiranja pokazuju da pozadinska stranica i dalje ponekad može da se pomeri kada dođete do samog vrha ili dna menija.
Kako sprečiti prekomerno skrolovanje na pozadinskoj stranici
Primjenom ovog rešenje, postaje moguće sprečiti "overscrolling". To znači da kada je element skrolovan do samog vrha ili dna, skrolovanje ne prelazi u telo stranice.
Kao rezultat toga, telo stranice se sprečava da se pomera tokom skrolovanja, čime se onemogućava i efekat elastičnog vraćanja (rubber-band efekat).
function removeIOSRubberEffect(element) {
element.addEventListener("touchstart", function() {
var top = element.scrollTop,
totalScroll = element.scrollHeight,
currentScroll = top + element.offsetHeight;
if (top === 0) {
element.scrollTop = 1;
} else if (currentScroll === totalScroll) {
element.scrollTop = top - 1;
}
});
}
removeIOSRubberEffect(document.querySelector(".scrollable"));
Ovaj JavaScript primer sprečava da element stigne do samog vrha ili dna tako što ga održava 1 piksel udaljenim.
Ako pozicija skrolovanja nikada ne dosegne apsolutni vrh ili dno, overskrolovanje nije moguće.
Kako sprečiti prelazak na pozadinsku stranicu prilikom skrolovanja preko kraja stranice
Ako želite da uklonite efekat gumene trake iz menija — bilo iz estetskih razloga ili zato što je, kao i u mom slučaju, prouzrokovao dodatne greške pri renderovanju — jednostavno uklonite CSS pravilo -webkit-overflow-scrolling.
Međutim, kao što vidite ispod, takođe gubite inerciju glatkog skrolovanja.
Ceo izvorni kod stranice
Evo celog izvornog koda stranice.
<!-- License MIT, Author Special Agent Squeaky (specialagentsqueaky.com) --> <!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="minimum-scale=1.0, width=device-width, maximum-scale=1.0, user-scalable=no, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style> .page{ font-size: 24px; overflow: scroll; } .menu{ position: fixed; top: 0; bottom: 0; left: 0; width: 80%; background: gray; z-index: 1; font-size: 10px; overflow: scroll; /* uncomment to get smooth momentum scroll, but also a rubber band effect */ /*-webkit-overflow-scrolling: touch;*/ } .menu-item{ padding: 10px; background: darkgray; font-size: 24px; } </style>
</head>
<body>
<div class="menu scrollable">
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
<div class="menu-item">hello world</div>
</div>
<div class="page disable-scrolling">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and scrambled it to make a type
specimen book. It has survived not only five centuries, but also the leap into
electronic typesetting, remaining essentially unchanged. It was popularised in
the 1960s with the release of Letraset sheets containing Lorem Ipsum passages,
and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
</div>
<script>
document.ontouchmove = function(event) {
var isTouchMoveAllowed = true,
target = event.target;
while (target !== null) {
if (target.classList && target.classList.contains('disable-scrolling')) {
isTouchMoveAllowed = false;
break;
}
target = target.parentNode;
}
if (!isTouchMoveAllowed) {
event.preventDefault();
}
};
function removeIOSRubberEffect(element) {
element.addEventListener("touchstart", function() {
var top = element.scrollTop,
totalScroll = element.scrollHeight,
currentScroll = top + element.offsetHeight;
if (top === 0) {
element.scrollTop = 1;
} else if (currentScroll === totalScroll) {
element.scrollTop = top - 1;
}
});
}
removeIOSRubberEffect(document.querySelector(".scrollable"));
</script>
</body>
</html>