Scrolling yang terkontrol dengan baik dengan CSS Scroll Snap

Buat pengalaman scroll yang terkontrol dengan baik dengan mendeklarasikan posisi pengepasan posisi scroll.

Fitur CSS Scroll Snap memungkinkan developer web membuat pengalaman scroll yang terkontrol dengan mendeklarasikan posisi pengepasan scroll. Artikel yang diberi nomor halaman dan carousel gambar adalah dua contoh yang umum digunakan. CSS Scroll Snap menyediakan API yang mudah digunakan dan konsisten untuk membangun pola UX populer ini.

Latar belakang

Kasus untuk pengepasan posisi scroll

Men-scroll adalah cara yang populer dan alami untuk berinteraksi dengan konten di web. Scroll adalah cara native platform untuk memberikan akses ke lebih banyak informasi daripada yang terlihat di layar sekaligus, yang menjadi sangat penting di platform seluler dengan ruang layar yang terbatas. Jadi, tidak mengherankan jika penulis web makin memilih untuk mengatur konten ke dalam daftar datar yang dapat di-scroll, bukan hierarki yang dalam.

Kelemahan utama scroll adalah kurangnya presisi. Scroll jarang berakhir sejajar dengan paragraf atau kalimat. Hal ini bahkan lebih terlihat untuk konten yang diberi nomor halaman atau diperinci dengan batas yang bermakna saat scroll selesai di tengah halaman atau gambar, sehingga hanya terlihat sebagian. Kasus penggunaan ini memperoleh manfaat dari pengalaman scroll yang terkontrol dengan baik.

Developer web telah lama mengandalkan solusi berbasis JavaScript untuk mengontrol scroll guna membantu mengatasi kekurangan ini. Namun, solusi berbasis JavaScript gagal memberikan solusi fidelitas penuh karena kurangnya primitif penyesuaian scroll atau akses ke scroll gabungan. CSS Scroll Snap memastikan solusi yang cepat, fidelitas tinggi, dan mudah digunakan yang berfungsi secara konsisten di seluruh browser.

CSS Scroll Snap memungkinkan penulis web menandai setiap penampung scroll dengan batas untuk operasi scroll yang akan diselesaikan. Browser kemudian memilih posisi akhir yang paling sesuai, bergantung pada detail operasi scroll, tata letak dan visibilitas penampung scroll, serta detail posisi snap, lalu menganimasikannya dengan lancar. Kembali ke contoh sebelumnya, saat pengguna selesai men-scroll carousel, gambar yang terlihat akan diposisikan ke tempatnya. Tidak perlu penyesuaian scroll oleh JavaScript.

Contoh penggunaan pengepasan posisi scroll CSS dengan carousel gambar.
Contoh penggunaan pengepasan posisi scroll CSS dengan carousel gambar. Di sini, pengepasan posisi scroll memastikan bahwa di akhir scroll, bagian tengah horizontal gambar sejajar dengan bagian tengah horizontal penampung scroll.

Pengepasan Posisi Scroll CSS

Pengepasan posisi scroll adalah tindakan menyesuaikan offset scroll dari penampung scroll agar berada di posisi pengepasan yang diinginkan setelah operasi scroll selesai.

Penampung scroll dapat diikutsertakan dalam pengepasan posisi scroll menggunakan properti scroll-snap-type. Hal ini memberi tahu browser bahwa browser harus mempertimbangkan untuk merapatkan penampung scroll ini ke posisi rapat yang dihasilkan oleh turunannya. scroll-snap-type menentukan sumbu tempat scroll terjadi: x, y, atau both, dan ketatnya snapping: mandatory, proximity. Kita akan membahasnya lebih lanjut nanti.

Posisi snap dapat dihasilkan dengan mendeklarasikan perataan yang diinginkan pada elemen. Posisi ini adalah offset scroll tempat penampung scroll ancestor terdekat dan elemen disejajarkan seperti yang ditentukan untuk sumbu tertentu. Perataan berikut dapat dilakukan pada setiap sumbu: start, end, center.

Perataan start berarti tepi awal snapport penampung scroll harus sejajar dengan tepi awal area snap elemen. Demikian pula, perataan end dan center berarti bahwa tepi akhir atau tengah snapport penampung scroll harus sejajar dengan tepi akhir atau tengah area snap elemen.

Contoh berbagai perataan pada sumbu scroll horizontal.

Contoh berikut mengilustrasikan cara menggunakan konsep ini.

Kasus penggunaan umum untuk pengepasan posisi scroll adalah carousel gambar. Misalnya, untuk membuat carousel gambar horizontal yang dipaskan ke setiap gambar saat Anda men-scroll, kita dapat menentukan penampung scroll agar memiliki scroll-snap-type wajib pada sumbu horizontal. tetapkan setiap gambar ke scroll-snap-align: center untuk memastikan bahwa pemasangan memusatkan gambar dalam carousel.

#gallery {
  scroll-snap-type: x mandatory;
  overflow-x: scroll;
  display: flex;
}

#gallery img {
   scroll-snap-align: center;
}
<div id="gallery">
  <img src="cat.jpg">
  <img src="dog.jpg">
  <img src="another_cute_animal.jpg">
</div>

Karena posisi snap dikaitkan dengan elemen, algoritma snapping dapat menentukan kapan dan bagaimana snap dilakukan berdasarkan elemen dan ukuran penampung scroll. Misalnya, pertimbangkan kasus saat satu gambar lebih besar dari carousel. Algoritme snapping yang sederhana dapat mencegah pengguna menggeser untuk melihat gambar secara penuh. Namun, spesifikasi mengharuskan implementasi untuk mendeteksi kasus ini dan memungkinkan pengguna men-scroll dengan bebas di dalam gambar tersebut, hanya mengaitkan di tepinya.

Contoh: Halaman produk yang telah dijelajahi

Kasus umum lainnya yang dapat memanfaatkan pengepasan posisi scroll adalah halaman dengan beberapa bagian logis untuk di-scroll secara vertikal, misalnya, halaman produk biasa. scroll-snap-type: y proximity; lebih cocok untuk kasus seperti ini. Fitur ini tidak mengganggu saat pengguna men-scroll ke tengah bagian tertentu, tetapi juga akan mengarahkan dan menarik perhatian ke bagian baru saat pengguna men-scroll cukup dekat.

Berikut cara melakukannya:

article {
  scroll-snap-type: y proximity;
  /* Reserve space for header plus some extra space for sneak peeking. */
  scroll-padding-top: 15vh;
  overflow-y: scroll;
}
section {
  /* Snap align start. */
  scroll-snap-align: start;
}
header {
  position: fixed;
  height: 10vh;
}
<article>
  <header> Header </header>
  <section> Section One </section>
  <section> Section Two </section>
  <section> Section Three </section>
</article>

Padding dan margin scroll

Halaman produk memiliki header atas dengan posisi tetap. Desain ini juga meminta agar beberapa bagian atas tetap terlihat saat penampung scroll diposisikan agar memberikan petunjuk desain kepada pengguna tentang konten di atas.

Properti scroll-padding adalah properti CSS baru yang dapat digunakan untuk menyesuaikan area yang dapat dilihat secara efektif dari penampung scroll, atau snapport, yang digunakan saat menghitung perataan pengepasan posisi scroll. Properti ini menentukan inset terhadap kotak padding penampung scroll. Dalam contoh kita, inset tambahan 15vh ditambahkan ke bagian atas, yang menginstruksikan browser untuk mempertimbangkan posisi yang lebih rendah, 15vh di bawah tepi atas penampung scroll, sebagai tepi awal vertikalnya untuk pengepasan posisi scroll. Saat diposisikan, tepi awal elemen target pemosisian akan sejajar dengan posisi baru ini, sehingga menyisakan ruang di atasnya.

Properti scroll-margin menentukan jumlah awal yang digunakan untuk menyesuaikan kotak efektif target snap, mirip dengan cara kerja scroll-padding pada penampung scroll snap.

Anda mungkin telah memperhatikan bahwa kedua properti ini tidak memiliki kata "snap" di dalamnya. Hal ini disengaja karena properti tersebut benar-benar mengubah kotak untuk semua operasi scroll yang relevan dan bukan hanya pengepasan posisi scroll. Misalnya, Chrome mempertimbangkannya saat menghitung ukuran halaman untuk operasi scroll paging seperti PageDown dan PageUp, serta saat menghitung jumlah scroll untuk operasi Element.scrollIntoView().

Interaksi dengan API scroll lainnya

DOM Scrolling API

Pengepasan posisi scroll terjadi setelah semua operasi scroll, termasuk yang dimulai oleh skrip. Saat Anda menggunakan API seperti Element.scrollTo, browser akan menghitung posisi scroll yang diinginkan dari operasi, lalu menerapkan logika snap yang sesuai untuk menemukan lokasi snap akhir. Dengan demikian, skrip pengguna tidak perlu melakukan penghitungan manual untuk snapping.

Scroll yang lancar

Scroll halus mengontrol perilaku operasi scroll terprogram, sedangkan pengepasan posisi scroll menentukan tujuannya. Karena mengontrol aspek scroll ortogonal, keduanya dapat digunakan bersama dan saling melengkapi.

Perilaku overscroll

Overscroll behavior API mengontrol cara scroll dirantai di beberapa elemen dan tidak terpengaruh oleh pengepasan posisi scroll.

Peringatan dan praktik terbaik

Hindari penggunaan penangkapan wajib jika elemen target berjarak jauh. Hal ini dapat menyebabkan konten di antara posisi snap menjadi tidak dapat diakses.

Dalam banyak kasus, pengepasan posisi scroll dapat ditambahkan sebagai peningkatan tanpa perlu mendeteksi fitur. Jika diperlukan, gunakan @supports atau CSS.supports untuk mendeteksi dukungan untuk CSS Scroll Snap. Hindari penggunaan scroll-snap-type yang juga ada dalam spesifikasi yang tidak digunakan lagi.

Deteksi fitur di CSS

@supports (scroll-snap-align: start) {
  article {
    scroll-snap-type: y proximity;
    scroll-padding-top: 15vh;
    overflow-y: scroll;
  }
}

Deteksi fitur di JavaScript

if (CSS.supports('scroll-snap-align: start')) {
  // use css scroll snap
} else {
  // use fallback
}

Jangan berasumsi bahwa API scroll terprogram seperti Element.scrollTo selalu selesai pada offset scroll yang diminta. Pengepasan posisi scroll dapat menyesuaikan offset scroll setelah scroll terprogram selesai. Perhatikan bahwa ini bukanlah asumsi yang baik bahkan sebelum adanya pengepasan posisi scroll karena scroll mungkin telah terganggu karena alasan lain, tetapi hal ini terutama terjadi pada pengepasan posisi scroll.

Tugas mendatang

Pengalaman scroll menjadi fokus survei terbaru oleh tim Chrome. Hasil survei mengidentifikasi beberapa area yang memerlukan upaya tambahan untuk memperkecil kesenjangan antara library plugin dan CSS. Pekerjaan mendatang akan berfokus pada scroll-snap, termasuk:

  1. Ketersediaan dan kompatibilitas API di berbagai browser.
  2. Mengerjakan CSS API baru seperti scroll-start.
  3. Mengerjakan peristiwa JS baru seperti snapChanged().