TL; DR
Met de CSS-eigenschap overscroll-behavior
kunnen ontwikkelaars het standaard overflow-scrollgedrag van de browser overschrijven wanneer ze de boven-/onderkant van de inhoud bereiken. Gebruiksscenario's zijn onder meer het uitschakelen van de pull-to-refresh-functie op mobiel, het verwijderen van overscroll-glow en rubberbanding-effecten, en het voorkomen dat pagina-inhoud scrollt wanneer deze zich onder een modale/overlay bevindt.
Achtergrond
Scrollgrenzen en scrollketens
Scrollen is een van de meest fundamentele manieren om met een pagina te communiceren, maar bepaalde UX-patronen kunnen lastig zijn om mee om te gaan vanwege het eigenzinnige standaardgedrag van de browser. Neem als voorbeeld een app-lade met een groot aantal items waar de gebruiker mogelijk doorheen moet scrollen. Wanneer ze de bodem bereiken, stopt de overloopcontainer met scrollen omdat er geen inhoud meer is om te consumeren. Met andere woorden: de gebruiker bereikt een "scrollgrens". Maar kijk eens wat er gebeurt als de gebruiker blijft scrollen. De inhoud achter de lade begint te scrollen ! Het scrollen wordt overgenomen door de bovenliggende container; de hoofdpagina zelf in het voorbeeld.
Blijkt dat dit gedrag 'scroll chaining' wordt genoemd; het standaardgedrag van de browser bij het scrollen door inhoud. Vaak is de standaardinstelling best aardig, maar soms is deze niet wenselijk of zelfs onverwacht. Bepaalde apps willen mogelijk een andere gebruikerservaring bieden wanneer de gebruiker een scrollgrens bereikt.
Het pull-to-refresh-effect
Pull-to-refresh is een intuïtief gebaar dat populair wordt gemaakt door mobiele apps zoals Facebook en Twitter. Door een sociale feed naar beneden te halen en vrij te geven, ontstaat er nieuwe ruimte voor het laden van recentere berichten. Deze specifieke UX is zelfs zo populair geworden dat mobiele browsers zoals Chrome op Android hetzelfde effect hebben overgenomen. Als u bovenaan de pagina naar beneden veegt, wordt de hele pagina vernieuwd:
Voor situaties zoals de Twitter PWA kan het zinvol zijn om de native pull-to-refresh-actie uit te schakelen. Waarom? In deze app wil je waarschijnlijk niet dat de gebruiker per ongeluk de pagina vernieuwt. Er is ook de mogelijkheid om een dubbele vernieuwingsanimatie te zien! Als alternatief kan het leuker zijn om de actie van de browser aan te passen, zodat deze beter aansluit bij de branding van de site. Het ongelukkige deel is dat dit soort aanpassingen lastig uit te voeren was. Ontwikkelaars schrijven uiteindelijk onnodig JavaScript, voegen niet-passieve aanraakluisteraars toe (die het scrollen blokkeren) of plakken de hele pagina in een 100vw/vh <div>
(om te voorkomen dat de pagina overloopt). Deze oplossingen hebben goed gedocumenteerde negatieve effecten op de scrollprestaties.
Wij kunnen het beter doen!
Introductie van overscroll-behavior
De eigenschap overscroll-behavior
is een nieuwe CSS-functie die het gedrag regelt van wat er gebeurt als u over een container heen scrollt (inclusief de pagina zelf). Je kunt het gebruiken om scroll-chaining te annuleren, de pull-to-refresh-actie uit te schakelen/aan te passen, rubberbanding-effecten op iOS uit te schakelen (wanneer Safari overscroll-behavior
implementeert) en meer. Het beste is dat het gebruik van overscroll-behavior
geen nadelige invloed heeft op de paginaprestaties, zoals de hacks die in de intro worden genoemd!
De eigenschap heeft drie mogelijke waarden:
- automatisch - Standaard. Scrolls die afkomstig zijn van het element kunnen zich voortplanten naar voorouderelementen.
- bevatten - voorkomt scroll-chaining. Scrolls verspreiden zich niet naar voorouders, maar lokale effecten binnen het knooppunt worden getoond. Bijvoorbeeld het overscroll-gloeieffect op Android of het rubberen bandeffect op iOS, dat de gebruiker waarschuwt wanneer hij een scrollgrens heeft bereikt. Opmerking : het gebruik van
overscroll-behavior: contain
op hethtml
-element voorkomt overscroll-navigatieacties. - geen - hetzelfde als
contain
, maar het voorkomt ook overscroll-effecten binnen het knooppunt zelf (bijvoorbeeld Android-overscroll-gloed of iOS-rubberbanding).
Laten we enkele voorbeelden bekijken om te zien hoe overscroll-behavior
kunt gebruiken.
Voorkom dat scrolls uit een vast positie-element ontsnappen
Het chatbox-scenario
Overweeg een vast geplaatste chatbox die onderaan de pagina staat. De bedoeling is dat de chatbox een op zichzelf staand onderdeel is en los van de inhoud erachter scrollt. Vanwege scroll-chaining begint het document echter te scrollen zodra de gebruiker het laatste bericht in de chatgeschiedenis bezoekt.
Voor deze app is het passender om scrolls die afkomstig zijn uit de chatbox binnen de chat te laten blijven. We kunnen dat mogelijk maken 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 creëren we een logische scheiding tussen de scrollcontext van de chatbox en de hoofdpagina. Het eindresultaat is dat de hoofdpagina blijft staan wanneer de gebruiker de boven-/onderkant van de chatgeschiedenis bereikt. Scrolls die in de chatbox beginnen, verspreiden zich niet naar buiten.
Het pagina-overlayscenario
Een andere variant van het 'underscroll'-scenario is wanneer u inhoud ziet scrollen achter een overlay met een vaste positie . Een dood weggeef- overscroll-behavior
is op zijn plaats! De browser probeert behulpzaam te zijn, maar zorgt er uiteindelijk voor dat de site er buggy uitziet.
Voorbeeld - modaal met en zonder overscroll-behavior: contain
:
Pull-to-refresh uitschakelen
Het uitschakelen van de pull-to-refresh-actie is een enkele regel CSS . Voorkom gewoon scroll-chaining op het gehele viewport-definiërende element. 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 repareren we de dubbele pull-to-refresh-animaties in de chatbox-demo en kunnen we in plaats daarvan een aangepast effect implementeren dat een nettere laadanimatie gebruikt. De hele inbox vervaagt ook terwijl de inbox wordt vernieuwd:
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>
Overscroll-gloei- en elastiekeffecten worden uitgeschakeld
Om het bounce-effect uit te schakelen bij het raken van een scrollgrens, gebruik je overscroll-behavior-y: none
:
body {
/* Disables pull-to-refresh and overscroll glow effect.
Still keeps swipe navigations. */
overscroll-behavior-y: none;
}
Volledige demo
Alles bij elkaar genomen maakt de volledige chatbox-demo gebruik van overscroll-behavior
om een aangepaste pull-to-refresh-animatie te creëren en te voorkomen dat scrolls uit de chatbox-widget ontsnappen. Dit zorgt voor een optimale gebruikerservaring die lastig te realiseren zou zijn geweest zonder CSS- overscroll-behavior
.