Membuat komponen Stories

Ringkasan dasar tentang cara membangun pengalaman yang mirip dengan Instagram Stories di web.

Dalam postingan ini, saya ingin berbagi pemikiran tentang cara membuat komponen Stories untuk web yang responsif, mendukung navigasi keyboard, dan berfungsi di berbagai browser.

Demo

Jika Anda lebih suka demonstrasi langsung dalam membuat komponen Stories ini sendiri, lihat codelab komponen Stories.

Jika Anda lebih suka video, berikut versi YouTube dari postingan ini:

Ringkasan

Dua contoh populer UX Stories adalah Snapchat Stories dan Instagram Stories (belum lagi fleets). Dalam istilah UX umum, Cerita biasanya merupakan pola khusus seluler yang berfokus pada ketukan untuk menavigasi beberapa langganan. Misalnya, di Instagram, pengguna membuka story teman dan melihat-lihat gambar di dalamnya. Mereka biasanya melakukan ini dengan banyak teman sekaligus. Dengan mengetuk sisi kanan perangkat, pengguna akan langsung beralih ke story berikutnya dari teman tersebut. Dengan menggeser ke kanan, pengguna akan beralih ke teman lain. Komponen Cerita cukup mirip dengan carousel, tetapi memungkinkan navigasi array multi-dimensi, bukan array satu dimensi. Seolah-olah ada carousel di dalam setiap carousel. 🤯

Array multi-dimensi yang divisualisasikan menggunakan kartu. Dari kiri ke kanan adalah tumpukan kartu berbingkai ungu, dan di dalam setiap kartu terdapat 1-banyak kartu berbingkai cyan. Daftar dalam daftar.
Carousel teman ke-1
Carousel story "bertumpuk" ke-2
👍 Daftar dalam daftar, alias: array multi-dimensi

Memilih alat yang tepat untuk pekerjaan

Secara keseluruhan, menurut saya komponen ini cukup mudah dibuat, berkat beberapa fitur platform web yang penting. Mari kita bahas!

Petak CSS

Tata letak kami ternyata tidak terlalu sulit untuk CSS Grid karena dilengkapi dengan beberapa cara yang efektif untuk mengelola konten.

Tata letak Friends

Wrapper komponen .stories utama kami adalah scrollview horizontal yang mengutamakan perangkat seluler:

.stories {
  inline-size: 100vw;
  block-size: 100vh;

  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;

  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}

/* desktop constraint */
@media (hover: hover) and (min-width: 480px) {
  max-inline-size: 480px;
  max-block-size: 848px;
}
Menggunakan Mode Perangkat Chrome DevTools untuk menandai kolom yang dibuat oleh Grid

Mari kita uraikan tata letak grid tersebut:

  • Kami secara eksplisit mengisi area pandang di perangkat seluler dengan 100vh dan 100vw serta membatasi ukuran di desktop
  • / memisahkan template baris dan kolom kami
  • auto-flow diterjemahkan ke grid-auto-flow: column
  • Template autoflow adalah 100%, yang dalam hal ini adalah berapa pun lebar jendela scroll

Di ponsel, anggap ini seperti ukuran baris sebagai tinggi area pandang dan setiap kolom sebagai lebar area pandang. Melanjutkan contoh Snapchat Stories dan Instagram Stories, setiap kolom akan menjadi cerita teman. Kita ingin cerita teman berlanjut di luar area pandang sehingga kita memiliki tempat untuk men-scroll. Grid akan membuat berapa pun kolom yang diperlukan untuk menata letak HTML untuk setiap story teman, sehingga membuat penampung scroll yang dinamis dan responsif untuk kita. Grid memungkinkan kita memusatkan seluruh efek.

Promosi gabungan

Untuk setiap teman, kita memerlukan story mereka dalam status siap penomoran halaman. Sebagai persiapan untuk animasi dan pola menarik lainnya, saya memilih stack. Saat saya mengatakan tumpukan, maksudnya seperti Anda melihat sandwich dari atas, bukan dari samping.

Dengan petak CSS, kita dapat menentukan petak satu sel (yaitu persegi), tempat baris dan kolom berbagi alias ([story]), lalu setiap turunan ditetapkan ke ruang satu sel dengan alias tersebut:

.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.story {
  grid-area: story;
  background-size: cover;
  …
}

Hal ini membuat HTML kita mengontrol urutan tumpukan dan juga menjaga semua elemen tetap dalam alur. Perhatikan bahwa kita tidak perlu melakukan apa pun dengan pemosisian absolute atau z-index dan kita tidak perlu mengoreksi kotak dengan height: 100% atau width: 100%. Petak induk sudah menentukan ukuran area pandang gambar cerita, sehingga tidak ada komponen cerita ini yang perlu diberi tahu untuk mengisinya.

Titik Snap Scroll CSS

Spesifikasi Titik Snap Scroll CSS memudahkan penguncian elemen ke area pandang saat di-scroll. Sebelum properti CSS ini ada, Anda harus menggunakan JavaScript, dan itu… rumit, setidaknya. Lihat Memperkenalkan Titik Snap Scroll CSS oleh Sarah Drasner untuk mengetahui penjelasan yang bagus tentang cara menggunakannya.

Scroll horizontal tanpa dan dengan gaya scroll-snap-points. Tanpa itu, pengguna dapat men-scroll bebas seperti biasa. Dengan begitu, browser akan berhenti dengan mulus di setiap item.
orang tua
.stories {
  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}
Induk dengan overscroll menentukan perilaku snap.
anak
.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
Anak-anak memilih untuk menjadi target snap.

Saya memilih Scroll Snap Points karena beberapa alasan:

  • Aksesibilitas gratis. Spesifikasi Titik Pengepasan Posisi Scroll menyatakan bahwa menekan tombol Panah Kiri dan Panah Kanan akan berpindah-pindah titik pengepasan posisi scroll secara default.
  • Spesifikasi yang terus berkembang. Spesifikasi Scroll Snap Points terus mendapatkan fitur dan peningkatan baru, yang berarti komponen Stories saya mungkin akan terus menjadi lebih baik mulai sekarang.
  • Kemudahan penerapan. Scroll Snap Points praktis dibuat untuk kasus penggunaan paginasi horizontal yang berfokus pada sentuhan.
  • Inersia gaya platform gratis. Setiap platform akan men-scroll dan berhenti sesuai gayanya, bukan inersia yang dinormalisasi yang dapat memiliki gaya scroll dan berhenti yang aneh.

Kompatibilitas lintas browser

Kami menguji di Opera, Firefox, Safari, dan Chrome, serta Android dan iOS. Berikut ringkasan singkat fitur web yang memiliki perbedaan kemampuan dan dukungan.

Namun, ada beberapa CSS yang tidak diterapkan, sehingga beberapa platform saat ini tidak mendapatkan pengoptimalan UX. Saya senang karena tidak perlu mengelola fitur ini dan yakin bahwa fitur ini pada akhirnya akan menjangkau browser dan platform lain.

scroll-snap-stop

Carousel adalah salah satu kasus penggunaan UX utama yang mendorong pembuatan spesifikasi Titik Pengepasan Posisi Scroll CSS. Tidak seperti Stories, carousel tidak selalu harus berhenti pada setiap gambar setelah pengguna berinteraksi dengannya. Mungkin tidak masalah atau dianjurkan untuk berpindah-pindah carousel dengan cepat. Di sisi lain, Stories paling baik dijelajahi satu per satu, dan itulah yang disediakan scroll-snap-stop.

.user {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

Saat postingan ini ditulis, scroll-snap-stop hanya didukung di browser berbasis Chromium. Lihat Kompatibilitas browser untuk mengetahui info terbaru. Namun, ini bukan pemblokir. Artinya, di browser yang tidak didukung, pengguna dapat secara tidak sengaja melewati teman. Jadi, pengguna harus lebih berhati-hati, atau kita perlu menulis JavaScript untuk memastikan bahwa teman yang dilewati tidak ditandai sebagai dilihat.

Baca selengkapnya di spesifikasi jika Anda tertarik.

overscroll-behavior

Pernahkah Anda men-scroll modal, lalu tiba-tiba mulai men-scroll konten di balik modal? overscroll-behavior memungkinkan developer menjebak scroll tersebut dan tidak membiarkannya keluar. Cocok untuk berbagai acara. Komponen My Stories menggunakannya untuk mencegah gestur geser dan scroll tambahan keluar dari komponen.

.stories {
  overflow-x: auto;
  overscroll-behavior: contain;
}

Safari dan Opera adalah 2 browser yang tidak mendukung hal ini, dan itu tidak masalah. Pengguna tersebut akan mendapatkan pengalaman overscroll seperti yang biasa mereka lakukan dan mungkin tidak akan pernah menyadari peningkatan ini. Saya pribadi sangat menyukainya dan suka menyertakannya sebagai bagian dari hampir setiap fitur overscroll yang saya terapkan. Penambahan ini tidak berbahaya dan hanya dapat meningkatkan UX.

scrollIntoView({behavior: 'smooth'})

Saat pengguna mengetuk atau mengklik dan telah mencapai akhir kumpulan story teman, saatnya beralih ke teman berikutnya dalam kumpulan titik pengepasan posisi scroll. Dengan JavaScript, kita dapat mereferensikan teman berikutnya dan memintanya untuk di-scroll ke tampilan. Dukungan untuk dasar-dasar ini sangat bagus; setiap browser men-scroll-nya ke tampilan. Namun, tidak semua browser melakukannya 'smooth'. Artinya, elemen di-scroll ke tampilan, bukan diposisikan.

element.scrollIntoView({
  behavior: 'smooth'
})

Safari adalah satu-satunya browser yang tidak mendukung behavior: 'smooth' di sini. Lihat Kompatibilitas browser untuk mengetahui info terbaru.

Praktik Langsung

Setelah tahu cara saya melakukannya, bagaimana cara Anda melakukannya? Mari kita diversifikasi pendekatan kita dan pelajari semua cara untuk membangun di web. Buat demo, tweet saya versi Anda, dan saya akan menambahkannya ke bagian Remix komunitas di bawah.

Remix komunitas