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.
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 memanggilpreventDefault()
, 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
.