Ringkasan dasar tentang cara membuat tampilan scroll horizontal yang responsif untuk TV, ponsel, desktop, dll.
Dalam postingan ini, saya ingin berbagi pemikiran tentang cara membuat pengalaman scroll horizontal untuk web yang minimal, responsif, mudah diakses, dan berfungsi di seluruh browser dan platform (seperti TV!). Coba demonya.
Jika Anda lebih suka video, berikut versi YouTube postingan ini:
Ringkasan
Kita akan membuat tata letak scroll horizontal yang dimaksudkan untuk menghosting thumbnail
media atau produk. Komponen dimulai sebagai daftar <ul>
sederhana, tetapi
diubah dengan CSS menjadi pengalaman scroll yang memuaskan dan lancar, yang menampilkan
gambar dan memasukkannya ke petak. JavaScript ditambahkan untuk memfasilitasi interaksi indeks penjelajah, yang membantu pengguna keyboard melewati 100+ item.
Selain itu, kueri media eksperimental, prefers-reduced-data
, digunakan untuk mengubah
scroller media menjadi pengalaman scroller judul yang ringan.
Mulai dengan markup yang dapat diakses
Scroller media hanya terdiri dari beberapa komponen inti, yaitu daftar berisi item. Sebuah daftar, dalam bentuknya yang paling sederhana, dapat berpindah ke seluruh dunia dan dengan jelas dipakai oleh semua orang. Pengguna yang membuka halaman ini dapat menjelajahi daftar dan mengklik link untuk melihat item. Ini adalah basis kami yang dapat diakses.
Kirimkan daftar dengan elemen <ul>
:
<ul class="horizontal-media-scroller">
<li></li>
<li></li>
<li></li>
...
<ul>
Buat item daftar menjadi interaktif dengan elemen <a>
:
<li>
<a href="#">
...
</a>
</li>
Gunakan elemen <figure>
untuk merepresentasikan gambar dan teksnya secara semantik:
<figure>
<picture>
<img alt="..." loading="lazy" src="https://picsum.photos/500/500?1">
</picture>
<figcaption>Legends</figcaption>
</figure>
Perhatikan atribut alt
dan loading
di <img>
. Teks alternatif untuk scroller
media adalah peluang UX untuk membantu menghadirkan konteks tambahan thumbnail, atau sebagai
teks penggantian jika gambar tidak dimuat, atau menyediakan UI lisan untuk pengguna
yang mengandalkan teknologi pendukung seperti pembaca layar. Pelajari lebih lanjut dengan Lima aturan
emas untuk teks alternatif
yang mematuhi kebijakan.
Atribut loading
menerima kata kunci lazy
sebagai cara untuk memberi sinyal bahwa sumber gambar ini
harus diambil hanya saat gambar berada dalam area pandang. Cara ini sangat
bagus untuk daftar besar, karena pengguna hanya akan mendownload gambar untuk item yang mereka
scroll ke tampilan.
Mendukung preferensi skema warna pengguna
Gunakan color-scheme
sebagai tag <meta>
untuk memberi tahu browser bahwa halaman Anda
menginginkan gaya agen pengguna yang disediakan terang dan gelap. Mode gelap atau mode terang gratis, tergantung bagaimana Anda melihatnya:
<meta name="color-scheme" content="dark light">
Tag meta memberikan sinyal seawal mungkin, sehingga browser dapat memilih warna kanvas default gelap jika pengguna memiliki preferensi tema gelap. Artinya, navigasi antar-halaman situs tidak akan memberikan latar belakang kanvas putih di antara pemuatan. Tema gelap yang mulus di antara pemuatan, jauh lebih menarik di mata.
Pelajari lebih lanjut dari Thomas Steiner di https://web.dev/color-scheme/.
Menambahkan konten
Dengan struktur konten ul > li > a > figure > picture > img
di atas,
tugas berikutnya adalah menambahkan gambar dan judul untuk di-scroll. Saya telah mengemas demo dengan gambar dan teks
placeholder statis, tetapi jangan ragu untuk mendukungnya dari
sumber data favorit Anda.
Menambahkan gaya dengan CSS
Sekarang saatnya CSS mengambil daftar konten umum ini dan mengubahnya menjadi pengalaman. Netflix, App store, dan banyak situs serta aplikasi lainnya menggunakan area scroll horizontal untuk mengemas area pandang dengan kategori dan opsi.
Membuat tata letak scroller
Penting untuk menghindari pemotongan konten dalam tata letak atau bersandar pada pemotongan teks dengan elipsis. Banyak televisi memiliki penggulir media seperti yang satu ini, tetapi terlalu sering menggunakan konten elips. Tata letak ini tidak cocok. Ini juga memungkinkan konten media mengganti ukuran kolom, sehingga membuat 1 tata letak cukup fleksibel untuk menangani banyak kombinasi menarik.
Penampung memungkinkan penggantian ukuran kolom dengan memberikan ukuran default sebagai properti kustom. Tata letak petak ini memiliki opini tentang ukuran kolom, yang hanya mengelola spasi dan arah:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2); /* parent owned value for children to be relative to*/
margin: 0;
}
Properti khusus ini kemudian digunakan oleh elemen <picture>
untuk membuat rasio aspek dasar: sebuah kotak:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
& picture {
inline-size: var(--size);
block-size: var(--size);
}
}
Dengan hanya beberapa gaya minor lagi, selesaikan menu barebon dari scroller media:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
& > li {
display: inline-block; /* removes the list-item bullet */
}
& picture {
inline-size: var(--size);
block-size: var(--size);
}
}
Menyetel overflow
akan menyiapkan <ul>
untuk memungkinkan navigasi scroll dan keyboard
melalui daftarnya, lalu setiap elemen <li>
turunan langsung akan menghapus ::marker
-nya
dengan mendapatkan jenis tampilan inline-block
baru.
Gambar belum responsif, dan langsung keluar dari kotak. Kurangi penggunaan dengan beberapa ukuran, kecocokan, dan gaya batas, serta gradien latar belakang saat pemuatan lambat:
img {
/* smash into whatever box it's in */
inline-size: 100%;
block-size: 100%;
/* don't squish but do cover the space */
object-fit: cover;
/* soften the edges */
border-radius: 1ex;
overflow: hidden;
/* if empty, show a gradient placeholder */
background-image:
linear-gradient(
to bottom,
hsl(0 0% 40%),
hsl(0 0% 20%)
);
}
Padding scroll
Penyelarasan terhadap konten halaman, serta area permukaan scroll dari tepi ke tepi, sangat penting untuk komponen yang harmonis dan minimal.
Untuk membuat tata letak scroll tepi-ke-tepi yang selaras dengan garis tipografi
dan tata letak kami, gunakan padding
yang cocok dengan scroll-padding
:
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
padding-inline: var(--gap);
scroll-padding-inline: var(--gap);
padding-block: calc(var(--gap) / 2); /* make space for scrollbar and focus outline */
}
Perbaikan bug padding horizontal Hal di atas menunjukkan betapa mudahnya menempatkan container scroll, tetapi ada masalah kompatibilitas yang belum diselesaikan dengannya (namun, telah diperbaiki di Chromium 91 ke atas). Lihat di sini untuk mengetahui sekilas histori, tetapi versi singkatnya adalah padding tidak selalu diperhitungkan dalam tampilan scroll.
Untuk mengelabui browser agar menempatkan padding di akhir scroller, saya akan menargetkan gambar terakhir di setiap daftar dan menambahkan elemen pseudo yang merupakan jumlah padding yang diinginkan.
.horizontal-media-scroller > li:last-of-type figure {
position: relative;
&::after {
content: "";
position: absolute;
inline-size: var(--gap);
block-size: 100%;
inset-block-start: 0;
inset-inline-end: calc(var(--gap) * -1);
}
}
Menggunakan properti logis memungkinkan scroller media untuk berfungsi dalam mode penulisan dan arah dokumen apa pun.
Pengepasan scroll
Container scroll dengan tambahan dapat menjadi area pandang pengepasan dengan satu baris CSS, lalu turunan dapat menentukan bagaimana mereka ingin disejajarkan dengan area pandang tersebut.
.horizontal-media-scroller {
--size: 150px;
display: grid;
grid-auto-flow: column;
gap: calc(var(--gap) / 2);
margin: 0;
overflow-x: auto;
overscroll-behavior-inline: contain;
padding-inline: var(--gap);
scroll-padding-inline: var(--gap);
padding-block-end: calc(var(--gap) / 2);
scroll-snap-type: inline mandatory;
& figure {
scroll-snap-align: start;
}
}
Fokus
Inspirasi untuk komponen ini berasal dari popularitasnya yang sangat besar di TV, di App Store, dan banyak lagi. Banyak platform video game menggunakan scroller media yang sangat mirip dengan yang ini, sebagai tata letak layar utama yang utama. Fokus adalah momen UX yang besar, bukan hanya sedikit tambahan. Bayangkan menggunakan scroller media ini dari sofa dengan remote, beri interaksi tersebut beberapa peningkatan kecil:
.horizontal-media-scroller a {
outline-offset: 12px;
&:focus {
outline-offset: 7px;
}
@media (prefers-reduced-motion: no-preference) {
& {
transition: outline-offset .25s ease;
}
}
}
Tindakan ini menetapkan gaya garis batas fokus 7px
dari kotak, sehingga memberikan ruang yang
bagus. Jika pengguna tidak memiliki preferensi gerakan untuk mengurangi gerakan, offset
akan ditransisikan, sehingga memberikan gerakan halus ke peristiwa fokus.
Indeks keliling
Pengguna gamepad dan keyboard memerlukan perhatian khusus dalam daftar panjang konten scroll dan opsi ini. Pola umum untuk menyelesaikan masalah ini disebut indeks keliling. Ini terjadi saat penampung item berfokus pada keyboard, tetapi hanya 1 turunan yang diizinkan untuk mempertahankan fokus pada satu waktu. Satu item yang dapat difokuskan pada satu waktu ini dirancang untuk memungkinkan mengabaikan daftar item yang berpotensi panjang, bukan menekan tab sebanyak 50+ kali untuk mencapai akhir.
Ada 300 item dalam scroller pertama demo tersebut. Kita bisa melakukan yang lebih baik daripada membuat mereka melewati semuanya untuk mencapai bagian berikutnya.
Untuk membuat pengalaman ini, JavaScript perlu mengamati peristiwa keyboard dan peristiwa fokus. Saya membuat library open source kecil di npm untuk membantu memudahkan pengalaman pengguna ini. Berikut cara menggunakannya untuk 3 scroller:
import {rovingIndex} from 'roving-ux';
rovingIndex({
element: someElement
});
Demo ini membuat kueri dokumen untuk scroller dan setiap scroller akan memanggil fungsi rovingIndex()
. Teruskan elemen rovingIndex()
untuk mendapatkan pengalaman
keliling, seperti penampung daftar, dan pemilih kueri target, jika
target fokus bukan turunan langsung.
document.querySelectorAll('.horizontal-media-scroller')
.forEach(scroller =>
rovingIndex({
element: scroller,
target: 'a',
}))
Untuk mempelajari efek ini lebih lanjut, lihat library open source roving-ux.
Rasio aspek
Saat menulis postingan ini, dukungan untuk
aspect-ratio
berada di belakang
flag di Firefox, tetapi tersedia di browser Chromium atau dekoder. Karena
tata letak petak scroller media hanya menentukan arah dan spasi, ukuran dapat
berubah di dalam kueri media yang menampilkan dukungan rasio aspek.
Peningkatan progresif menjadi scroller media yang lebih dinamis.
@supports (aspect-ratio: 1) {
.horizontal-media-scroller figure > picture {
inline-size: auto; /* for a block-size driven ratio */
aspect-ratio: 1; /* boxes by default */
@nest section:nth-child(2) & {
aspect-ratio: 16/9;
}
@nest section:nth-child(3) & {
/* double the size of the others */
block-size: calc(var(--size) * 2);
aspect-ratio: 4/3;
/* adjust size to fit more items into the viewport */
@media (width <= 480px) {
block-size: calc(var(--size) * 1.5);
}
}
}
}
Jika browser mendukung sintaksis aspect-ratio
, gambar scroller media akan
diupgrade ke ukuran aspect-ratio
. Dengan menggunakan draf sintaksis bertingkat, setiap gambar
mengubah rasio aspek, bergantung pada apakah itu baris pertama, kedua, atau ketiga. Sintaksis bertingkat juga memungkinkan penetapan beberapa penyesuaian
area pandang kecil, bersama logika ukuran lainnya.
Dengan CSS tersebut, karena fitur tersedia di lebih banyak mesin browser, tata letak yang mudah dikelola tetapi lebih menarik secara visual akan dirender.
Mengutamakan pengurangan data
Meskipun teknik berikutnya ini hanya tersedia di belakang flag di Canary, saya ingin berbagi cara menghemat banyak waktu muat halaman dan penggunaan data dengan beberapa baris CSS. Kueri media prefers-reduced-data
dari
level 5 memungkinkan pertanyaan apakah perangkat dalam
status data yang dikurangi, seperti mode penghemat data. Jika ya, saya bisa memodifikasi dokumen, dan dalam hal ini, menyembunyikan gambarnya.
figure {
@media (prefers-reduced-data: reduce) {
& {
min-inline-size: var(--size);
& > picture {
display: none;
}
}
}
}
Konten masih dapat dijelajahi, tetapi tanpa harus mendownload gambar
yang berat. Berikut adalah situs sebelum menambahkan CSS prefers-reduced-data
:
(7 permintaan, 100 kb resource dalam 131 md)
Berikut adalah performa situs setelah menambahkan CSS prefers-reduced-data
:
(71 permintaan, 1,2 mb resource dalam 1,07 dtk)
64 permintaan lebih sedikit, yaitu ~60 gambar dalam area tampilan (pengujian yang dilakukan pada tampilan layar lebar) tab browser ini, peningkatan pemuatan halaman sebesar ~80%, dan 10% data melalui kabel. CSS yang cukup canggih.
Kesimpulan
Sekarang Anda tahu bagaimana saya melakukannya, bagaimana Anda akan?! 🙂
Mari lakukan diversifikasi pendekatan dan pelajari semua cara untuk membangun di web. Buat Codepen atau host demo Anda sendiri, kirim tweet, dan saya akan menambahkannya ke bagian remix Komunitas di bawah.
Sumber
Remix komunitas
Belum ada apa-apa di sini.