Przejmij kontrolę nad przewijaniem – dostosuj efekty przeciągnięcia, aby odświeżyć lub przepełnienia

TL;DR

Właściwość CSS overscroll-behavior pozwala deweloperom zastąpić domyślne zachowanie przewijania przy przepełnieniu, gdy użytkownik dotrze do góry lub do dołu treści. Przykłady zastosowań obejmują wyłączenie funkcji przeciągania do odświeżenia na urządzeniach mobilnych, usunięcie efektu poświaty i efektu gumki oraz uniemożliwienie przewijania zawartości strony, gdy znajduje się ona pod modalem lub nakładką.

Tło

Granice przewijania i łańcuchowanie przewijania

Przewijanie łańcuchów w Chrome na Androida

Przewijanie jest jednym z podstawowych sposobów interakcji ze stroną, ale niektóre wzorce UX mogą być trudne do zastosowania ze względu na dziwaczne domyślne zachowania przeglądarki. Weźmy na przykład panel aplikacji z dużą liczbą elementy, które użytkownik będzie musiał przewinąć. Gdy użytkownik dotrze do dołu, przewijanie kontenera przepełnionego treściami zostanie zatrzymane, ponieważ nie ma już więcej treści do wyświetlenia. Innymi słowy, użytkownik osiągnie „granicę przewijania”. Zwróć uwagę, co się dzieje, gdy użytkownik przewija dalej. Treści za szufladą zaczynają się przewijać. Przewijanie jest przejęte przez kontener nadrzędny; samej strony głównej z przykładu.

Okazuje się, że to zachowanie nazywa się łańcuchowanie przewijania. Jest to domyślne zachowanie przeglądarki podczas przewijania treści. Domyślnie ustawienia domyślne są całkiem dobre, czasami jest to niepożądane lub nawet nieoczekiwane. Niektóre aplikacje mogą chcieć zapewniają inne wrażenia użytkownikom, którzy przekraczają granicę przewijania.

Efekt „przeciągnij, by odświeżyć”

Przeciąganie w dół w celu odświeżenia jest intuicyjnym gestem znanym z aplikacji mobilnych, takich jak Facebook czy Twitter. Przeciągnięcie w dół i puszczenie palca powoduje utworzenie nowego miejsca na załadowanie nowszych postów. W fakcie ten interfejs użytkownika stał się tak popularny, że przeglądarki mobilne, takie jak Chrome na Androidzie, zaczęły stosować ten sam efekt. Przesunięcie palcem w dół u góry strony powoduje odświeżenie całej strony:

Dostosowany przez Twittera element „przeciągnij, aby odświeżyć”
, który pojawia się podczas odświeżania kanału w aplikacji PWA.
Domyślne działanie „przeciągnij, aby odświeżyć” w Chrome na Androida
odświeża całą stronę.

W przypadku aplikacji internetowych, takich jak Twitter, warto wyłączyć działanie natywne „przeciągnij, aby odświeżyć”. Dlaczego? W tej aplikacji prawdopodobnie nie chcesz, aby użytkownik przypadkowo odświeżał stronę. Możesz też zobaczyć podwójną animację odświeżania. Być może lepiej dostosować działanie przeglądarki, ściślej dostosowując ją marki. Niestety tego rodzaju dostosowania trudno się wydostać. W końcu programiści piszą zbędny kod JavaScript, niepasywny detektor dotyku (blokujący przewijanie) lub całą stronę <div> (aby zapobiec przepełnieniu strony). Te obejścia mają dobrze udokumentowane negatywne skutki dla wydajności przewijania.

Stać nas na więcej!

Przedstawiamy overscroll-behavior

Właściwość overscroll-behavior to nowa funkcja CSS, która kontroluje zachowanie, jakie występuje, gdy przewiniesz kontener (w tym samą stronę) poza ekran. Możesz go użyć, aby anulować łańcuch przewijania, wyłączyć lub dostosować funkcję przewijania przez pociągnięcie, wyłączyć efekt gumki na iOS (gdy Safari wdroży overscroll-behavior) i wykonywać inne czynności. Co najlepsze, korzystanie z overscroll-behavior nie wpływa negatywnie na wydajność strony, takie jak ataki opisane we wstępie.

Właściwość może przyjmować 3 wartości:

  1. auto – domyślne. Przewijanie, które pochodzi z elementu, może być przekazywane do elementów nadrzędnych.
  2. contain – zapobiega tworzeniu łańcuchów przewijania. Przewijanie nie jest przekazywane do przodków, ale wyświetlane są efekty lokalne w węźle. Na przykład efekt poświaty przy przewijaniu na Androidzie lub efekt gumki na iOS, który informuje użytkownika, gdy osiągnie on granicę przewijania. Uwaga: użycie overscroll-behavior: contain w elemencie html zapobiega nadmiernemu przewijaniu działań nawigacyjnych.
  3. none – działa tak samo jak contain, ale zapobiega efektom przewinięcia w ciągu sam węzeł (np. efekt sygnalizowania końca przewijania w Androidzie lub gumka typu gumka w iOS).

Przyjrzyjmy się kilku przykładom, aby dowiedzieć się, jak używać atrybutu overscroll-behavior.

Zapobieganie przesuwaniu się elementów poza element o stałym położeniu

Scenariusz rozmowy

Treści pod oknem czatu też się przewijają :(

Rozważ użycie okna czatu w stałym położeniu na dole strony. Chodzi o to, aby okno czatu było samodzielnym elementem, który można przewijać niezależnie od treści znajdujących się za nim. Jednak ze względu na łańcuch przewijania dokument zaczyna się przewijać, gdy tylko użytkownik kliknie ostatnią wiadomość w historii czatu.

W przypadku tej aplikacji bardziej odpowiednie są przewijanie, które pochodzą z pozostają na czacie. Aby to zrobić, dodaj element overscroll-behavior: contain do elementu zawierającego wiadomości czatu:

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

W podstawie chodzi o logiczne oddzielenie kontekstu przewijania czatu od strony głównej. Efektem jest to, że strona główna pozostaje użytkownik przechodzi do górnej lub dolnej części historii czatu. Przewinięcia rozpoczynające się od okno czatu nie jest rozpowszechniane.

Scenariusz rozmowy z informacjami o nakładce na stronie

Innym wariantem scenariusza „podwijania” jest sytuacja, gdy widzisz treści przewijane za nakładką w stałym położeniu. Zdecydowanie warto skorzystać z promocji overscroll-behavior. Przeglądarka próbuje być pomocna, ale w efekcie sprawia, że witryna wygląda na pełną błędów.

Przykład – tryb modalny z parametrem overscroll-behavior: contain i bez niego:

Przed: zawartość strony przewija się pod nakładką.
Po: zawartość strony nie przewija się pod nakładką.

Wyłączam odświeżanie metodą „przeciągnij, aby”

Wyłączenie działania „przeciągnij, aby odświeżyć” to pojedyncza linijka kodu CSS. Wystarczy zablokować łańcuch przewijania w całym elemencie definiującym obszar widoku. W większości przypadków jest to <html> lub <body>:

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

Dzięki temu prostemu dodatkowi możemy naprawić podwójne animacje przeciągania do odświeżenia w demo okna czatu i zamiast tego wdrożyć efekt niestandardowy, który wykorzystuje ładniejszą animację ładowania. Cała skrzynka odbiorcza jest też rozmyta podczas jej odświeżania:

Przed
Po

Oto fragment pełnego kodu:

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

Wyłączanie efektu poświaty i efektu gumki

Aby wyłączyć efekt odbicia po dotarciu do granicy przewijania, użyj funkcji overscroll-behavior-y: none:

body {
  /* Disables pull-to-refresh and overscroll glow effect.
     Still keeps swipe navigations. */
  overscroll-behavior-y: none;
}
Przed: po dotknięciu granicy przewijania pojawia się poświata.
Po: poświata wyłączona.

Pełna prezentacja

W całości demo czatu wykorzystuje element overscroll-behavior do tworzenia niestandardowej animacji odświeżania po przeciągnięciu oraz blokuje przewijanie poza widget czatu. Dzięki temu użytkownicy będą mieli optymalne wrażenia, których trudno byłoby osiągnąć bez CSS.overscroll-behavior

Zobacz prezentację | Źródło