Touch-scrollen is standaard snel

Dave Tapuska
Dave Tapuska

We weten dat het reactievermogen bij het scrollen van cruciaal belang is voor de betrokkenheid van de gebruiker bij een website op mobiel, maar luisteraars voor aanraakgebeurtenissen veroorzaken vaak ernstige prestatieproblemen bij het scrollen. Chrome heeft dit aangepakt door toe te staan ​​dat luisteraars van aanraakgebeurtenissen passief zijn (door de optie {passive: true} door te geven aan addEventListener() ) en door de API voor pointergebeurtenissen te verzenden. Dit zijn geweldige functies om nieuwe inhoud in modellen te verwerken die het scrollen niet blokkeren, maar ontwikkelaars vinden het soms moeilijk om ze te begrijpen en toe te passen.

Wij zijn van mening dat het internet standaard snel moet zijn, zonder dat ontwikkelaars geheimzinnige details van browsergedrag hoeven te begrijpen. In Chrome 56 stellen we aanraakluisteraars standaard in op passief in gevallen waarin dat meestal overeenkomt met de bedoeling van de ontwikkelaar. Wij zijn van mening dat we door dit te doen de gebruikerservaring aanzienlijk kunnen verbeteren, terwijl we een minimale negatieve impact op sites hebben.

In zeldzame gevallen kan deze wijziging resulteren in onbedoeld scrollen. Dit kan meestal eenvoudig worden verholpen door een aanraakactie : geen stijl toe te passen op het element waar niet mag worden gescrolld. Lees verder voor meer informatie, hoe u weet of u hierdoor wordt getroffen en wat u eraan kunt doen.

Achtergrond: Annuleerbare evenementen vertragen uw pagina

Als u preventieDefault() aanroept in de touchstart of first touchmove gebeurtenissen, voorkomt u scrollen. Het probleem is dat luisteraars preventDefault() meestal niet zullen aanroepen, maar dat de browser moet wachten tot de gebeurtenis is voltooid om daar zeker van te zijn. Door de ontwikkelaar gedefinieerde "passieve gebeurtenislisteners" lossen dit op. Wanneer u een touch-gebeurtenis toevoegt met een {passive: true} -object als de derde parameter in uw gebeurtenishandler, vertelt u de browser dat de touchstart listener preventDefault() niet zal aanroepen en dat de browser veilig kan scrollen zonder de luisteraar. Bijvoorbeeld:

window.addEventListener("touchstart", func, {passive: true} );

De interventie

Onze belangrijkste motivatie is het verkorten van de tijd die nodig is om het scherm bij te werken nadat de gebruiker het scherm heeft aangeraakt. Om het gebruik van touchstart en touchmove te begrijpen, hebben we statistieken toegevoegd om te bepalen hoe vaak scrollblokkeringsgedrag optrad.

We hebben gekeken naar het percentage annuleerbare aanraakgebeurtenissen dat naar een hoofddoel (venster, document of hoofdtekst) is verzonden en hebben vastgesteld dat ongeveer 80% van deze luisteraars conceptueel passief zijn, maar niet als zodanig zijn geregistreerd. Gezien de omvang van dit probleem zagen we een geweldige kans om het scrollen te verbeteren zonder enige actie van de ontwikkelaar, door deze gebeurtenissen automatisch "passief" te maken.

Dit bracht ons ertoe onze interventie als volgt te definiëren: als het doelwit van een touchstart- of touchmove-luisteraar het window , document of body is, stellen we passive in op true . Dit betekent dat code als:

window.addEventListener("touchstart", func);

wordt gelijk aan:

window.addEventListener("touchstart", func, {passive: true} );

Nu worden oproepen naar preventDefault() binnen de luisteraar genegeerd.

De onderstaande grafiek toont de tijd die de bovenste 1% van de scrolls nodig heeft vanaf het moment dat een gebruiker het scherm aanraakt om te scrollen tot het moment waarop het display wordt bijgewerkt. Deze gegevens gelden voor alle websites in Chrome voor Android. Voordat de interventie werd ingeschakeld, duurde 1% van de scrolls iets meer dan 400 ms. Dat is nu teruggebracht tot iets meer dan 250 ms in Chrome 56 Bèta; een reductie van ongeveer 38%. In de toekomst hopen we van passief waar de standaard te maken voor alle touchstart en touchmove luisteraars, waardoor dit wordt teruggebracht tot minder dan 50 ms.

Grafiek met de bovenste 1% scrolltijden

Breuk en begeleiding

In de overgrote meerderheid van de gevallen zal er geen breuk worden waargenomen. Maar als er toch breuk optreedt, is het meest voorkomende symptoom dat scrollen gebeurt wanneer u dat niet wilt. In zeldzame gevallen kunnen ontwikkelaars ook onverwachte klikgebeurtenissen opmerken (wanneer preventDefault() ontbrak in een touchend listener).

In Chrome 56 en hoger registreert DevTools een waarschuwing wanneer u preventDefault() aanroept in een gebeurtenis waarbij de interventie actief is.

touch-passive.html:19 Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/5093566007214080

Uw toepassing kan bepalen of dit mogelijk in het wild voorkomt door te controleren of het aanroepen preventDefault enig effect heeft gehad via de eigenschap defaultPrevented .

We hebben ontdekt dat een grote meerderheid van de getroffen pagina's relatief eenvoudig kan worden opgelost door waar mogelijk de CSS-eigenschap met aanraakactie toe te passen. Als u wilt voorkomen dat de browser binnen een element scrollt en zoomt, past u touch-action: none toe. Als je een horizontale carrousel hebt, overweeg dan om touch-action: pan-y pinch-zoom erop, zodat de gebruiker nog steeds verticaal kan scrollen en kan zoomen zoals normaal. Het correct toepassen van aanraakacties is al nodig in browsers zoals desktop Edge die aanwijzergebeurtenissen ondersteunen en geen aanraakgebeurtenissen. Voor mobiele Safari en oudere mobiele browsers die geen aanraakactie ondersteunen, moeten uw aanraakluisteraars preventDefault blijven aanroepen, zelfs als dit door Chrome wordt genegeerd.

In complexere gevallen kan het nodig zijn om ook op een van de volgende te vertrouwen:

  • Als uw touchstart listener preventDefault() aanroept, zorg er dan voor dat preventieDefault() ook wordt aangeroepen door gekoppelde touchend-listeners om het genereren van klikgebeurtenissen en ander standaard tikgedrag te blijven onderdrukken.
  • Laatste (en afgeraden) passeer {passive: false} aan addEventListener() om het standaardgedrag te overschrijven. Houd er rekening mee dat u moet detecteren of de User Agent EventListenerOptions ondersteunt.

Conclusie

In Chrome 56 begint het scrollen op veel websites aanzienlijk sneller. Dit is de enige impact die de meeste ontwikkelaars zullen merken als gevolg van deze wijziging. In sommige gevallen kunnen ontwikkelaars onbedoeld scrollen opmerken.

Hoewel het nog steeds nodig is om dit te doen voor mobiele Safari, mogen websites niet vertrouwen op het aanroepen van preventDefault() binnen touchstart en touchmove listeners, aangezien dit niet langer gegarandeerd wordt gehonoreerd in Chrome. Ontwikkelaars moeten de CSS-eigenschap touch-action toepassen op elementen waar scrollen en zoomen moeten worden uitgeschakeld om de browser op de hoogte te stellen voordat er aanraakgebeurtenissen plaatsvinden. Als u het standaardgedrag van een tik (zoals het genereren van een klikgebeurtenis) wilt onderdrukken, roept u preventDefault() op in een touchend listener.