Bitte beachten Sie, dass dieser Blogbeitrag im Juni 2015 veröffentlicht wurde. Je nachdem, wann Sie ihn lesen, können Teile veraltet sein. Leider kann ich diese Beiträge nicht immer auf dem neuesten Stand halten, um die Richtigkeit der Informationen zu gewährleisten.
- Meine Testseite
- Das Standardverhalten verstehen
- Verstehen, was die CSS-Regel „-webkit-overflow-scrolling“ bewirkt
- Der Benutzer muss warten, bis der Gummiband-Effekt abgeschlossen ist.
- So verhindern Sie das Scrollen der Hintergrundseite.
- So verhindern Sie, dass beim Scrollen die Hintergrundseite mitgescrollt wird.
- So verhindern Sie Overscroll zur Hintergrundseite.
- Quellcode der gesamten Seite
Um ein kürzliches Scrollproblem in Safari auf iOS zu beheben, musste ich eine eigene, einfache Testseite erstellen und anschließend alle Informationen und Ansätze aus dem Internet ausprobieren, die ich finden konnte, um das Problem zu lösen.
Nachfolgend finden Sie eine kurze Übersicht darüber, was ich während dieses Prozesses herausgefunden habe.
Meine Testseite
Meine Testseite war recht einfach aufgebaut. Sie bestand aus Mock-Daten in einem statischen Div, um die „Seite“ darzustellen, und zusätzlich aus einem festen Div, das ein darüber liegendes „Menü“ darstellt – so sieht es aus.
Der vollständige Quellcode der Seite befindet sich am Ende dieses Blogbeitrags.
Das Standardverhalten verstehen
Das Erste, was ich tat, war herauszufinden, wie Safari auf iOS standardmäßig funktioniert. Die auffälligste Beobachtung war, dass der Seiteninhalt beim Scrollen bis ganz nach unten im Menü den Gummiband-Effekt zeigte – eine fest kodierte Funktion in Safari.
Dasselbe passierte, als man im Menü ganz nach oben scrollte.
Allerdings war das erste Problem, das mir aufgefallen ist, dass Safari, wenn man ständig bis ganz nach oben oder unten scrollt, Darstellungsfehler sowohl auf der Hintergrundseite als auch im Menü zeigt.
Ich bin mir nicht sicher, warum das so ist, aber ich vermute, es hat etwas mit der Gummiband-Funktion zu tun.
Verstehen, was die CSS-Regel „-webkit-overflow-scrolling“ bewirkt
Als Nächstes habe ich die CSS-Regel -webkit-overflow-scrolling auf das Menü angewendet, die Scrollen mit Trägheit ermöglicht.
Wie im untenstehenden Bild zu sehen ist, scrollt die Seite weiter, auch nachdem ich mit dem Finger darüber gewischt habe.
Es erzeugt außerdem einen Gummiband-Effekt, wenn man ganz nach oben oder ganz nach unten scrollt, wie unten gezeigt.
Der Benutzer muss warten, bis der Gummiband-Effekt abgeschlossen ist.
Während meiner Tests ist mir außerdem aufgefallen, dass der Benutzer den Fokus auf ein anderes Element nicht verschieben kann, solange der Gummiband-Effekt läuft, bis die Animation vollständig abgeschlossen ist.
Im unten gezeigten Beispiel scrolle ich zuerst die Hintergrundseite nach unten und versuche dann schnell, das Menü zu scrollen – am Ende scrolle ich jedoch weiter auf der Hintergrundseite.
Wenn ich jedoch einen Moment warte, bis der Effekt vorbei ist, kann ich danach im Menü scrollen.
So verhindern Sie das Scrollen der Hintergrundseite.
Während meiner Tests ist mir außerdem aufgefallen, dass der Benutzer während des Gummiband-Effekts den Fokus nicht auf ein anderes Element verschieben kann, bis die Animation vollständig abgeschlossen ist.
Basierend auf dieser Antwort von Stack Overflow kannst du sicherstellen, dass Elemente mit disable-scrolling ihr Standard-Scroll-Verhalten nicht ausführen, wenn das touchmove-Ereignis ausgelöst wird.
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();
}
};
Und wende anschließend die Klasse disable-scrolling auf das Div-Element der Seite an:
<div class="page disable-scrolling">
Das klappt schon ganz gut, aber umfangreichere Tests zeigen, dass die Hintergrundseite trotzdem manchmal scrollt, wenn man ganz oben oder ganz unten im Menü ankommt.
So verhindern Sie, dass beim Scrollen die Hintergrundseite mitgescrollt wird.
Durch das Anwenden dieser Lösung lässt sich Overscrolling verhindern. Das bedeutet, dass beim Scrollen eines Elements bis ganz nach oben oder ganz nach unten das Scrollen nicht weiter in den Seiteninhalt hinein fortgesetzt wird.
Dadurch wird das Scrollen des Seiteninhalts verhindert, wodurch auch der Gummiband-Effekt nicht mehr auftritt.
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"));
Dieses JavaScript-Snippet sorgt dafür, dass das Element nie ganz oben oder ganz unten landet – es bleibt immer 1 Pixel davon entfernt.
Wenn die Scrollposition niemals den absoluten oberen oder unteren Rand erreicht, kann ein Overscroll niemals auftreten.
So verhindern Sie Overscroll zur Hintergrundseite.
Wenn Sie den Gummiband-Effekt im Menü entfernen möchten – sei es aus ästhetischen Gründen oder weil er, wie in meinem Fall, zu zusätzlichen Rendering-Problemen geführt hat – entfernen Sie einfach die CSS-Regel -webkit-overflow-scrolling.
Allerdings geht, wie unten zu sehen ist, auch die sanfte Scroll-Bewegung verloren.
Quellcode der gesamten Seite
Hier ist der vollständige Quellcode der Seite.
<!-- 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>