Neem de controle over je scrollen: pas de effecten voor omlaag trekken om te vernieuwen en overloop aan

In het kort

Met de css-property overscroll-behavior kunnen ontwikkelaars het standaard scrollgedrag van de browser overschrijven als de boven- of onderkant van de content wordt bereikt. Use cases zijn onder andere de functie Trek omlaag om te vernieuwen uitzetten op mobiele apparaten, de effecten van overscroll-gloed en rubberbanding verwijderen en voorkomen dat paginacontent scrollt als deze zich onder een modaal/overlay bevindt.

Achtergrond

Scrollgrenzen en scrollketens

Scroll chaining in Chrome op Android.

Scrollen is een van de meest fundamentele manieren om interactie met een pagina te hebben, maar bepaalde UX-patronen kunnen lastig zijn vanwege het eigenzinnige standaardgedrag van de browser. Neem bijvoorbeeld een app-lade met een groot aantal items waar de gebruiker doorheen moet scrollen. Als ze de onderkant bereiken, stopt de overloopcontainer met scrollen omdat er geen content meer is om te consumeren. Met andere woorden: de gebruiker bereikt een scrollgrens. Maar let op wat er gebeurt als de gebruiker verder scrollt. De content achter de lade begint te scrollen. Scrollen wordt overgenomen door de bovenliggende container, in het voorbeeld de hoofdpagina zelf.

Dit gedrag wordt scroll chaining genoemd en is het standaardgedrag van de browser bij het scrollen door content. Vaak is de standaardinstelling prima, maar soms is deze niet wenselijk of zelfs onverwacht. Bepaalde apps willen misschien een andere gebruikerservaring bieden als de gebruiker een scrollgrens bereikt.

Het effect van trekken om te vernieuwen

Trek omlaag om te vernieuwen is een intuïtief gebaar dat populair is geworden door mobiele apps zoals Facebook en Twitter. Als je een social feed naar beneden trekt en loslaat, ontstaat er nieuwe ruimte om recentere posts te laden. Deze specifieke UX is zelfs zo populair geworden dat mobiele browsers zoals Chrome op Android hetzelfde effect hebben overgenomen. Als je bovenaan de pagina omlaag swipet, wordt de hele pagina vernieuwd:

De aangepaste functie 'trek omlaag om te vernieuwen' van Twitter
bij het vernieuwen van een feed in hun PWA.
De systeemeigen actie 'trek omlaag om te vernieuwen' van Chrome voor Android
vernieuwt de hele pagina.

In situaties zoals de Twitter-PWA, kan het zinvol zijn om de systeemeigen actie voor omlaag trekken om te vernieuwen uit te zetten. Waarom? In deze app wil je waarschijnlijk niet dat de gebruiker de pagina per ongeluk vernieuwt. Er is ook een kans dat je een dubbele vernieuwingsanimatie ziet. Het kan ook leuker zijn om de actie van de browser aan te passen, zodat deze beter aansluit bij de branding van de site. Het nadeel is dat dit type aanpassing lastig te realiseren is. Ontwikkelaars schrijven onnodige JavaScript, voegen niet-passieve touch-listeners toe (die scrollen blokkeren) of plaatsen de hele pagina in een 100vw/vh <div> (om te voorkomen dat de pagina overloopt). Deze tijdelijke oplossingen hebben goed gedocumenteerde negatieve effecten op de scrollprestaties.

Dat kunnen we beter!

Nieuw: overscroll-behavior

De overscroll-behavior -property is een nieuwe CSS-functie die bepaalt wat er gebeurt als je te ver scrollt in een container (waaronder de pagina zelf). Je kunt deze eigenschap gebruiken om scroll chaining te annuleren, de actie 'trekken om te vernieuwen' uit te zetten of aan te passen, rubberbanding-effecten op iOS uit te zetten (als Safari overscroll-behavior implementeert) en meer. Het beste is dat het gebruik van overscroll-behavior geen negatieve invloed heeft op de paginaprestaties, zoals de hacks die in de inleiding worden genoemd.

De property heeft 3 mogelijke waarden:

  1. auto: Standaard. Scrollbewegingen die op het element beginnen, kunnen worden doorgegeven aan bovenliggende elementen.
  2. contain: voorkomt scrollketens. Scrollen wordt niet doorgegeven aan bovenliggende elementen, maar lokale effecten binnen de node worden wel getoond. Bijvoorbeeld het overscroll-gloei-effect op Android of het rubberbanding-effect op iOS, dat de gebruiker laat weten wanneer deze een scrollgrens heeft bereikt. Opmerking: Als je overscroll-behavior: contain gebruikt voor het element html, voorkom je navigatieacties voor overscrollen.
  3. none: hetzelfde als contain, maar voorkomt ook overscroll-effecten binnen de node zelf (bijvoorbeeld Android-overscroll-gloed of iOS-rubberbanding).

Laten we een paar voorbeelden doornemen om te zien hoe je overscroll-behavior gebruikt.

Voorkomen dat scrollen een element met een vaste positie verlaat

Het chatboxscenario

Content beneath the chat window scrolls too :(

Overweeg een vastgezet chatvak onderaan de pagina. Het is de bedoeling dat de chatbox een op zichzelf staand component is en dat deze afzonderlijk van de content erachter scrollt. Maar door scroll chaining begint het document te scrollen zodra de gebruiker het laatste bericht in de chatgeschiedenis bereikt.

Voor deze app is het beter als scrolls die in de chatbox beginnen, in de chat blijven. We kunnen dit doen door overscroll-behavior: contain toe te voegen aan het element dat de chatberichten bevat:

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

In wezen maken we een logische scheiding tussen de scrollcontext van de chatbox en de hoofdpagina. Het eindresultaat is dat de hoofdpagina blijft staan als de gebruiker de boven- of onderkant van de chatgeschiedenis bereikt. Scrollen dat begint in het chatvak, wordt niet doorgegeven.

Het scenario voor pagina-overlay

Een andere variant van het scenario 'underscroll' is wanneer u content ziet scrollen achter een overlay met vaste positie. Een weggevertje overscroll-behavior is op zijn plaats. De browser probeert te helpen, maar het zorgt ervoor dat de site er buggy uitziet.

Voorbeeld: modaal met en zonder overscroll-behavior: contain:

Eerder: paginacontent scrollt onder de overlay.
Na: paginacontent scrollt niet onder de overlay.

Trek omlaag om te vernieuwen uitzetten

Je kunt de actie 'trekken om te vernieuwen' uitzetten met één regel CSS. Voorkom gewoon scroll chaining op het hele element dat de viewport definieert. In de meeste gevallen is dat <html> of <body>:

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

Met deze eenvoudige toevoeging lossen we de dubbele animaties voor omlaag trekken om te vernieuwen op in de chatbox-demo. In plaats daarvan kunnen we een aangepast effect implementeren dat een nettere laadanimatie gebruikt. De hele inbox wordt ook wazig terwijl de inbox wordt vernieuwd:

Voor
Na

Hier is een fragment van de volledige code:

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

Gloed bij overscrollen en rubberbanding-effecten uitzetten

Gebruik overscroll-behavior-y: none om het bounce-effect uit te zetten als je een scrollgrens bereikt:

body {
  /* Disables pull-to-refresh and overscroll glow effect.
     Still keeps swipe navigations. */
  overscroll-behavior-y: none;
}
Eerder: Als je de scrollgrens bereikt, wordt er een gloed getoond.
Na: gloed uitgezet.

Volledige demo

In de volledige chatboxdemo wordt overscroll-behavior gebruikt om een aangepaste animatie voor omlaag trekken om te vernieuwen te maken en te voorkomen dat scrollen de chatboxwidget verlaat. Dit biedt een optimale gebruikerservaring die zonder CSS moeilijk te bereiken zou zijn geweest. overscroll-behavior

Demo bekijken | Bron