Behalte die Kontrolle über das Scrollen – mit der Option „Zum Aktualisieren ziehen“ und „Überlauf“ kannst du die Effekte anpassen

Kurzfassung

Mit der CSS-Property overscroll-behavior können Entwickler das standardmäßige Scrollverhalten des Browsers überschreiben, wenn der Anfang oder das Ende des Inhalts erreicht wird. Zu den Anwendungsfällen gehören das Deaktivieren der Funktion „Zum Aktualisieren nach unten ziehen“ auf Mobilgeräten, das Entfernen von Overscroll-Glow- und Rubberbanding-Effekten sowie das Verhindern des Scrollens von Seiteninhalten, wenn sie sich unter einem Modal/Overlay befinden.

Hintergrund

Scrollgrenzen und Scrollverkettung

Scrollverkettung in Chrome für Android.

Scrollen ist eine der grundlegendsten Möglichkeiten, mit einer Seite zu interagieren. Bestimmte UX-Muster können jedoch aufgrund des ungewöhnlichen Standardverhaltens des Browsers schwierig zu handhaben sein. Nehmen wir als Beispiel eine App-Leiste mit einer großen Anzahl von Elementen, durch die der Nutzer scrollen muss. Wenn sie das Ende erreichen, wird der Überlaufcontainer nicht mehr gescrollt, da keine Inhalte mehr vorhanden sind. Mit anderen Worten: Der Nutzer erreicht eine „Scrollgrenze“. Aber sehen Sie, was passiert, wenn der Nutzer weiter scrollt. Der Inhalt hinter der Einblendung wird gescrollt. Das Scrollen wird vom übergeordneten Container übernommen, im Beispiel von der Hauptseite selbst.

Dieses Verhalten wird als Scrollverkettung bezeichnet und ist das Standardverhalten des Browsers beim Scrollen von Inhalten. Oft ist die Standardeinstellung ganz gut, aber manchmal ist sie nicht wünschenswert oder sogar unerwartet. In bestimmten Apps soll möglicherweise eine andere Nutzererfahrung geboten werden, wenn der Nutzer eine Scrollgrenze erreicht.

Der Effekt „Zum Aktualisieren nach unten ziehen“

„Zum Aktualisieren nach unten ziehen“ ist eine intuitive Geste, die durch mobile Apps wie Facebook und Twitter bekannt wurde. Wenn Sie einen Social-Media-Feed nach unten ziehen und loslassen, wird neuer Platz für neuere Beiträge geschaffen. Diese UX ist sogar so beliebt geworden, dass mobile Browser wie Chrome unter Android denselben Effekt übernommen haben. Wenn Sie oben auf der Seite nach unten wischen, wird die gesamte Seite aktualisiert:

Die benutzerdefinierte Funktion „Zum Aktualisieren nach unten ziehen“ von Twitter
beim Aktualisieren eines Feeds in der PWA.
Die native Aktion „Zum Aktualisieren nach unten ziehen“
von Chrome für Android aktualisiert die gesamte Seite.

In Situationen wie der Twitter-PWA kann es sinnvoll sein, die native Aktion „Zum Aktualisieren nach unten ziehen“ zu deaktivieren. Was ist der Grund dafür? In dieser App möchten Sie wahrscheinlich nicht, dass der Nutzer die Seite versehentlich aktualisiert. Es besteht auch die Möglichkeit, dass eine doppelte Aktualisierungsanimation angezeigt wird. Alternativ kann es besser sein, die Aktion des Browsers anzupassen und sie stärker an das Branding der Website anzupassen. Leider ist diese Art der Anpassung schwierig umzusetzen. Entwickler schreiben unnötiges JavaScript, fügen nicht passive Touch-Listener hinzu (die das Scrollen blockieren) oder fügen die gesamte Seite in ein 100vw/vh-<div> ein (um zu verhindern, dass die Seite überläuft). Diese Problemumgehungen haben gut dokumentierte negative Auswirkungen auf die Scrollleistung.

Das können wir besser!

Jetzt neu: overscroll-behavior

Die Eigenschaft overscroll-behavior ist ein neues CSS-Feature, mit dem das Verhalten gesteuert wird, wenn ein Container (einschließlich der Seite selbst) überscrollt wird. Sie können damit die Scrollverkettung abbrechen, die Aktion „Zum Aktualisieren nach unten ziehen“ deaktivieren/anpassen, Rubberbanding-Effekte unter iOS deaktivieren (wenn Safari overscroll-behavior implementiert) und vieles mehr. Das Beste daran ist, dass die Verwendung von overscroll-behavior die Seitenleistung nicht beeinträchtigt, wie es bei den in der Einleitung erwähnten Hacks der Fall ist.

Die Property kann drei mögliche Werte annehmen:

  1. auto: Standardeinstellung. Scrollvorgänge, die auf dem Element beginnen, können an übergeordnete Elemente weitergegeben werden.
  2. contain: Verhindert Scrollverkettung. Scrollvorgänge werden nicht an übergeordnete Elemente weitergegeben, aber lokale Effekte innerhalb des Knotens werden angezeigt. Beispiele hierfür sind der Overscroll-Glow-Effekt unter Android oder der Rubberbanding-Effekt unter iOS, die den Nutzer benachrichtigen, wenn er an eine Scrollgrenze stößt. Hinweis: Wenn Sie overscroll-behavior: contain für das html-Element verwenden, werden Navigationsaktionen beim Overscroll verhindert.
  3. none: Wie contain, verhindert aber auch Overscroll-Effekte innerhalb des Knotens selbst (z.B. Android-Overscroll-Glühen oder iOS-Rubberbanding).

Sehen wir uns einige Beispiele an, wie overscroll-behavior verwendet wird.

Verhindern, dass Scrollvorgänge ein Element mit fester Position verlassen

Das Chatbox-Szenario

Der Inhalt unter dem Chatfenster wird auch gescrollt :(

Nehmen wir als Beispiel ein Chatfeld, das unten auf der Seite fixiert ist. Die Chatbox soll eine eigenständige Komponente sein, die unabhängig vom Inhalt dahinter gescrollt wird. Aufgrund der Scrollverkettung beginnt das Dokument jedoch zu scrollen, sobald der Nutzer die letzte Nachricht im Chatverlauf erreicht.

Für diese App ist es besser, wenn Scrollvorgänge, die innerhalb des Chatfelds beginnen, auch im Chat bleiben. Das können wir erreichen, indem wir dem Element, das die Chatnachrichten enthält, overscroll-behavior: contain hinzufügen:

#chat .msgs {
  overflow: auto;
  overscroll-behavior: contain;
  height: 300px;
}

Im Wesentlichen erstellen wir eine logische Trennung zwischen dem Scrollkontext des Chatfelds und der Hauptseite. Das Ergebnis ist, dass die Hauptseite an Ort und Stelle bleibt, wenn der Nutzer den Anfang oder das Ende des Chatverlaufs erreicht. Scrollvorgänge, die in der Chatbox beginnen, werden nicht nach außen weitergegeben.

Szenario: Seiten-Overlay

Eine weitere Variante des „Underscroll“-Szenarios ist, wenn Inhalte hinter einem Overlay mit fester Position gescrollt werden. Ein Dead Giveaway overscroll-behavior ist fällig! Der Browser versucht, hilfreich zu sein, aber am Ende sieht die Website fehlerhaft aus.

Beispiel – modales Fenster mit und ohne overscroll-behavior: contain:

Vorher: Der Seiteninhalt wird unter dem Overlay gescrollt.
Nachher: Der Seiteninhalt scrollt nicht unter dem Overlay.

„Zum Aktualisieren nach unten ziehen“ deaktivieren

Das Deaktivieren der Aktion „Zum Aktualisieren nach unten ziehen“ ist eine einzelne Zeile CSS. Verhindern Sie einfach die Scrollverkettung für das gesamte Element, das den Darstellungsbereich definiert. In den meisten Fällen ist das <html> oder <body>:

body {
  /* Disables pull-to-refresh but allows overscroll glow effects. */
  overscroll-behavior-y: contain;
}

Mit dieser einfachen Ergänzung beheben wir die doppelten Animationen zum Aktualisieren nach unten in der Chatbox-Demo und können stattdessen einen benutzerdefinierten Effekt mit einer übersichtlicheren Ladeanimation implementieren. Der gesamte Posteingang wird beim Aktualisieren unscharf dargestellt:

Vorher
Nachher

Hier ist ein Snippet des vollständigen Codes:

<style>
  body.refreshing #inbox {
    filter: blur(1px);
    touch-action: none; /* prevent scrolling */
  }
  body.refreshing .refresher {
    transform: translate3d(0,150%,0) scale(1);
    z-index: 1;
  }
  .refresher {
    --refresh-width: 55px;
    pointer-events: none;
    width: var(--refresh-width);
    height: var(--refresh-width);
    border-radius: 50%;
    position: absolute;
    transition: all 300ms cubic-bezier(0,0,0.2,1);
    will-change: transform, opacity;
    ...
  }
</style>

<div class="refresher">
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
  <div class="loading-bar"></div>
</div>

<section id="inbox"><!-- msgs --></section>

<script>
  let _startY;
  const inbox = document.querySelector('#inbox');

  inbox.addEventListener('touchstart', e => {
    _startY = e.touches[0].pageY;
  }, {passive: true});

  inbox.addEventListener('touchmove', e => {
    const y = e.touches[0].pageY;
    // Activate custom pull-to-refresh effects when at the top of the container
    // and user is scrolling up.
    if (document.scrollingElement.scrollTop === 0 && y > _startY &&
        !document.body.classList.contains('refreshing')) {
      // refresh inbox.
    }
  }, {passive: true});
</script>

Deaktivierung des Overscroll-Leuchtens und des Rubberbanding-Effekts

Mit overscroll-behavior-y: none können Sie den Bounce-Effekt beim Erreichen einer Scrollgrenze deaktivieren:

body {
  /* Disables pull-to-refresh and overscroll glow effect.
     Still keeps swipe navigations. */
  overscroll-behavior-y: none;
}
Vorher: Wenn die Scrollgrenze erreicht wird, wird ein Leuchten angezeigt.
Nachher: Leuchten deaktiviert.

Vollständige Demo

In der vollständigen Chatbox-Demo wird overscroll-behavior verwendet, um eine benutzerdefinierte Animation für das Aktualisieren durch Herunterziehen zu erstellen und zu verhindern, dass das Scrollen das Chatbox-Widget verlässt. So wird eine optimale Nutzererfahrung ermöglicht, die ohne CSS-overscroll-behavior nur schwer zu erreichen gewesen wäre.

Demo ansehen | Quelle