Membuat scroll sentuh cepat secara default

Dave Tapuska
Dave Tapuska

Kita tahu bahwa responsivitas scroll sangat penting bagi interaksi pengguna dengan situs di perangkat seluler, tetapi pemroses peristiwa sentuh sering menyebabkan masalah performa scroll yang serius. Chrome telah mengatasi hal ini dengan mengizinkan pemroses peristiwa sentuh menjadi pasif (meneruskan opsi {passive: true} ke addEventListener()) dan mengirimkan peristiwa pointer API. Ini adalah fitur yang bagus untuk mendorong konten baru ke dalam model yang tidak memblokir scrolling, tetapi developer terkadang merasa sulit untuk memahami dan mengadopsinya.

Kami percaya bahwa web harus cepat secara default tanpa perlu developer memahami detail perilaku browser yang rumit. Di Chrome 56, kami menyetel pemroses sentuh untuk pasif secara default jika pemroses sering kali cocok dengan niat developer. Kami percaya bahwa dengan melakukan hal ini, kami dapat meningkatkan pengalaman pengguna secara signifikan sekaligus meminimalkan dampak negatif terhadap situs.

Dalam kasus yang jarang terjadi, perubahan ini dapat mengakibatkan scroll yang tidak diinginkan. Hal ini biasanya mudah ditangani dengan menerapkan tindakan sentuh: gaya none pada elemen tempat scroll tidak seharusnya terjadi. Baca terus untuk mengetahui detail, cara mengetahui apakah Anda terdampak, dan apa yang dapat Anda lakukan.

Latar belakang: Peristiwa yang Dapat Dibatalkan memperlambat halaman Anda

Jika memanggil preventDefault() pada peristiwa touchstart atau touchmove pertama, Anda akan mencegah scrolling. Masalahnya adalah sebagian besar pemroses tidak akan memanggil preventDefault(), tetapi browser harus menunggu peristiwa selesai untuk memastikannya. "Pemroses peristiwa pasif" yang ditentukan developer akan mengatasi masalah ini. Saat menambahkan peristiwa sentuh dengan objek {passive: true} sebagai parameter ketiga dalam pengendali peristiwa, Anda akan memberi tahu browser bahwa pemroses touchstart tidak akan memanggil preventDefault() dan browser dapat melakukan scroll dengan aman tanpa memblokir pemroses. Contoh:

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

Intervensi

Motivasi utama kami adalah mengurangi waktu yang diperlukan untuk memperbarui layar setelah pengguna menyentuh layar. Untuk memahami penggunaan touchstart dan touchmove kami menambahkan metrik untuk menentukan seberapa sering perilaku pemblokiran scroll terjadi.

Kami melihat persentase peristiwa sentuh yang dapat dibatalkan yang dikirim ke target root (jendela, dokumen, atau isi) dan menentukan bahwa sekitar 80% pemroses ini secara konseptual pasif, tetapi tidak terdaftar seperti itu. Mengingat skala masalah ini, kami melihat peluang besar untuk meningkatkan scroll tanpa tindakan developer apa pun dengan membuat peristiwa ini otomatis "pasif".

Hal ini mendorong kami untuk menentukan intervensi sebagai: jika target pemroses touchstart atau touchmove adalah window, document, atau body, secara default passive ke true. Ini berarti kode seperti:

window.addEventListener("touchstart", func);

menjadi setara dengan:

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

Sekarang, panggilan ke preventDefault() di dalam pemroses akan diabaikan.

Grafik di bawah menunjukkan waktu yang dibutuhkan oleh 1% scroll teratas dari saat pengguna menyentuh layar untuk men-scroll hingga waktu tampilan diperbarui. Data ini ditujukan untuk semua situs di Chrome untuk Android. Sebelum intervensi diaktifkan, 1% scroll memerlukan waktu lebih dari 400 milidetik. Sekarang kecepatannya telah berkurang menjadi hanya 250 md di Chrome 56 Beta; pengurangan sekitar 38%. Di masa mendatang, kami berharap dapat menjadikan benar pasif sebagai default untuk semua pemroses touchstart dan touchmove, sehingga mengurangi waktu menjadi di bawah 50 md.

Grafik 1% waktu sroll teratas

Kerusakan dan Panduan

Dalam sebagian besar kasus, kerusakan tidak akan terlihat. Namun, saat kerusakan terjadi, gejala yang paling umum adalah scroll terjadi saat Anda tidak menginginkannya. Dalam kasus yang jarang terjadi, developer mungkin juga melihat peristiwa klik yang tidak terduga (saat preventDefault() tidak ada dari pemroses touchend).

Di Chrome 56 dan yang lebih baru, DevTools akan mencatat peringatan saat Anda memanggil preventDefault() jika intervensi aktif.

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

Aplikasi Anda dapat menentukan apakah itu mungkin terjadi secara liar dengan memeriksa apakah pemanggilan preventDefault berpengaruh melalui properti defaultPrevented.

Kami menemukan bahwa sebagian besar halaman yang terpengaruh relatif mudah diperbaiki dengan menerapkan properti CSS touch-action jika memungkinkan. Jika Anda ingin mencegah semua scrolling dan zoom browser dalam elemen, terapkan touch-action: none ke elemen tersebut. Jika Anda memiliki carousel horizontal, pertimbangkan untuk menerapkan touch-action: pan-y pinch-zoom agar pengguna masih dapat men-scroll secara vertikal dan melakukan zoom seperti biasa. Menerapkan tindakan sentuh dengan benar sudah diperlukan di browser seperti Edge desktop yang mendukung Peristiwa Pointer, bukan Peristiwa Sentuh. Untuk Safari seluler dan browser seluler lama yang tidak mendukung tindakan sentuh, pemroses sentuh Anda harus terus memanggil preventDefault meskipun akan diabaikan oleh Chrome.

Dalam kasus yang lebih kompleks, Anda mungkin juga perlu mengandalkan salah satu hal berikut:

  • Jika pemroses touchstart Anda memanggil preventDefault(), pastikan preventDefault() juga dipanggil dari pemroses touchend terkait untuk terus menyembunyikan pembuatan peristiwa klik dan perilaku ketuk default lainnya.
  • Terakhir (dan tidak disarankan) teruskan {passive: false} ke addEventListener() untuk mengganti perilaku default. Perhatikan bahwa Anda harus mendeteksi fitur jika Agen Pengguna mendukung EventListenerOptions.

Kesimpulan

Di Chrome 56, pengguliran dimulai jauh lebih cepat di banyak situs web. Inilah satu-satunya dampak yang akan dilihat oleh sebagian besar developer sebagai hasil dari perubahan ini. Dalam beberapa kasus, developer mungkin melihat scroll yang tidak diinginkan.

Meskipun masih diperlukan untuk melakukannya untuk Safari seluler, situs tidak boleh mengandalkan preventDefault() di dalam pemroses touchstart dan touchmove karena hal ini tidak lagi dijamin akan diterapkan di Chrome. Developer harus menerapkan properti CSS touch-action pada elemen tempat scroll dan zoom harus dinonaktifkan untuk memberi tahu browser sebelum peristiwa sentuh terjadi. Untuk menyembunyikan perilaku default ketukan (seperti pembuatan peristiwa klik), panggil preventDefault() di dalam pemroses touchend.