Kendalikan scroll Anda - menyesuaikan efek pull-to-refresh dan overflow

TL;DR (Ringkasan)

Properti overscroll-behavior CSS memungkinkan developer mengganti perilaku scroll tambahan default browser saat mencapai bagian atas/bawah konten. Kasus penggunaan mencakup penonaktifan fitur tarik untuk refresh di perangkat seluler, menghapus glow overscroll dan efek rubberbanding, serta mencegah konten halaman di-scroll saat berada di bawah modal/overlay.

Latar belakang

Batas scroll dan rantai scroll

Perantai scroll di Chrome Android.

Men-scroll adalah salah satu cara paling mendasar untuk berinteraksi dengan halaman, tetapi pola UX tertentu mungkin sulit ditangani karena perilaku default default dari browser. Sebagai contoh, ambil panel daftar aplikasi dengan banyak item yang mungkin harus di-scroll oleh pengguna. Saat mencapai bagian bawah, penampung tambahan akan berhenti men-scroll karena tidak ada lagi konten untuk digunakan. Dengan kata lain, pengguna mencapai "batas scroll". Namun, perhatikan apa yang terjadi jika pengguna terus men-scroll. Konten di belakang panel samping mulai di-scroll. Scroll diambil oleh penampung induk; halaman utama itu sendiri dalam contoh.

Ternyata perilaku ini disebut scroll chaining; perilaku default browser saat men-scroll konten. Sering kali {i>default-<i}nya cukup bagus, tetapi terkadang tidak diinginkan atau bahkan tidak terduga. Aplikasi tertentu mungkin ingin memberikan pengalaman pengguna yang berbeda saat pengguna mencapai batas scroll.

Efek tarik untuk refresh

Tarik untuk refresh adalah gestur intuitif yang dipopulerkan oleh aplikasi seluler seperti Facebook dan Twitter. Menarik ke umpan sosial dan melepaskannya akan menciptakan ruang baru untuk memuat postingan terbaru. Faktanya, UX khusus ini telah menjadi sangat populer sehingga browser seluler seperti Chrome di Android telah menggunakan efek yang sama. Menggeser ke bawah di bagian atas halaman akan menyegarkan seluruh halaman:

Tarik untuk dimuat ulang kustom Twitter
saat memuat ulang feed di PWA mereka.
Tindakan tarik untuk refresh native Chrome Android
memuat ulang seluruh halaman.

Untuk situasi seperti PWA Twitter, sebaiknya nonaktifkan tindakan pull-to-refresh native. Mengapa demikian? Dalam aplikasi ini, Anda mungkin tidak ingin pengguna memuat ulang halaman secara tidak sengaja. Ada kemungkinan untuk melihat animasi refresh ganda. Atau, mungkin akan lebih baik untuk menyesuaikan tindakan browser, sehingga lebih menyelaraskannya dengan branding situs. Bagian yang disayangkan adalah jenis penyesuaian ini sulit untuk dilakukan. Developer akhirnya menulis JavaScript yang tidak perlu, menambahkan pemroses sentuh non-pasif (yang memblokir scroll), atau menempelkan seluruh halaman dengan <div> 100vw/vh (untuk mencegah halaman meluap). Solusi ini memiliki efek negatif yang terdokumentasi dengan baik terhadap performa scroll.

Kita bisa lebih baik lagi!

Memperkenalkan overscroll-behavior

Properti overscroll-behavior adalah fitur CSS baru yang mengontrol perilaku apa yang terjadi saat Anda men-scroll penampung secara berlebihan (termasuk halaman itu sendiri). Anda dapat menggunakannya untuk membatalkan perantaian scroll, menonaktifkan/menyesuaikan tindakan tarik untuk refresh, menonaktifkan efek rubberbanding di iOS (saat Safari menerapkan overscroll-behavior), dan banyak lagi. Bagian terbaiknya adalah menggunakan overscroll-behavior tidak berdampak buruk pada performa halaman seperti peretasan yang disebutkan di bagian pengantar.

Properti ini memiliki tiga kemungkinan nilai:

  1. auto - Default. Scroll yang berasal dari elemen dapat menyebar ke elemen ancestor.
  2. contain - mencegah rantai scroll. Scroll tidak menyebar ke ancestor, tetapi efek lokal dalam node ditampilkan. Misalnya, efek glow overscroll di Android atau efek rubberbanding di iOS yang memberi tahu pengguna saat mereka telah mencapai batas scroll. Catatan: penggunaan overscroll-behavior: contain pada elemen html akan mencegah tindakan navigasi overscroll.
  3. none - sama seperti contain, tetapi juga mencegah efek overscroll dalam node itu sendiri (misalnya, glow overscroll Android atau rubberbanding iOS).

Mari kita pelajari beberapa contoh untuk melihat cara menggunakan overscroll-behavior.

Mencegah scroll meng-escape elemen posisi tetap

Skenario kotak chat

Konten yang ada di bawah jendela chat juga akan di-scroll :(

Pertimbangkan kotak chat yang diposisikan dengan tetap yang berada di bagian bawah halaman. Tujuannya adalah agar kotak chat menjadi komponen yang berdiri sendiri dan di-scroll secara terpisah dari konten di belakangnya. Namun, karena rantai scroll, dokumen mulai di-scroll segera setelah pengguna mencapai pesan terakhir dalam histori chat.

Untuk aplikasi ini, akan lebih tepat untuk memiliki scroll yang berasal dari kotak chat tetap berada dalam chat. Kita dapat melakukannya dengan menambahkan overscroll-behavior: contain ke elemen yang menyimpan pesan chat:

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

Pada dasarnya, kita membuat pemisahan logis antara konteks scroll kotak chat dan halaman utama. Hasil akhirnya adalah halaman utama tetap ditampilkan saat pengguna mencapai bagian atas/bawah histori chat. Scroll yang dimulai di kotak chat tidak akan menyebar.

Skenario overlay halaman

Variasi lain dari skenario "underscroll" adalah saat Anda melihat konten di-scroll di belakang overlay posisi tetap. Hadiah belum tentu overscroll-behavior sudah tepat! {i>Browser<i} mencoba membantu, tetapi akhirnya membuat situs terlihat berisi bug.

Contoh - modal dengan dan tanpa overscroll-behavior: contain:

Sebelum: konten halaman di-scroll di bawah overlay.
Setelah: konten halaman tidak di-scroll di bawah overlay.

Menonaktifkan tarik untuk refresh

Menonaktifkan tindakan tarik untuk refresh adalah satu baris CSS. Cukup jangan membuat rantai scroll di seluruh elemen yang menentukan area pandang. Dalam sebagian besar kasus, parameter tersebut adalah <html> atau <body>:

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

Dengan penambahan sederhana ini, kita memperbaiki animasi tarik untuk refresh ganda dalam demo chatbox dan dapat menerapkan efek kustom yang menggunakan animasi pemuatan yang lebih rapi. Seluruh kotak masuk juga menjadi blur saat kotak masuk dimuat ulang:

Sebelum
Setelah

Berikut adalah cuplikan kode lengkap:

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

Menonaktifkan efek glow overscroll dan rubberband

Untuk menonaktifkan efek pantulan saat mencapai batas scroll, gunakan overscroll-behavior-y: none:

body {
  /* Disables pull-to-refresh and overscroll glow effect.
     Still keeps swipe navigations. */
  overscroll-behavior-y: none;
}
Sebelum: mencapai batas scroll akan menampilkan glow.
Sesudah: glow dinonaktifkan.

Demo lengkap

Menyatukan semuanya, demo chatbox lengkap menggunakan overscroll-behavior untuk membuat animasi pull-to-refresh kustom dan menonaktifkan scroll agar tidak keluar dari widget kotak chat. Hal ini memberikan pengalaman pengguna optimal yang akan sulit dicapai tanpa CSS overscroll-behavior.

Lihat demo | Sumber