Ringkasan dasar tentang cara membangun scrollview horizontal responsif untuk TV, ponsel, desktop, dll.
Dalam postingan ini, saya ingin berbagi pemikiran tentang cara membuat scroll horizontal yang minimal, responsif, mudah diakses, dan dapat berfungsi di berbagai {i>browser<i} dan platform (seperti TV!). Mulai demo.
Jika Anda lebih suka menonton video, berikut versi YouTube untuk postingan ini:
Ringkasan
Kita akan membangun tata letak gulir horizontal
yang dimaksudkan untuk menghosting {i>thumbnail<i}
media atau produk. Komponen ini dimulai sebagai daftar <ul>
sederhana, tetapi
diubah dengan CSS menjadi pengalaman scroll yang memuaskan dan lancar, yang menampilkan
gambar dan mengepaskannya ke {i>grid<i}. JavaScript ditambahkan untuk memfasilitasi
interaksi indeks keliling, membantu pengguna keyboard melewati lebih dari 100 item.
Selain itu, kueri media eksperimental, prefers-reduced-data
, digunakan untuk mengubah
scroller media ke pengalaman scroller judul yang ringan.
Mulai dengan markup yang mudah diakses
Scroller media hanya terdiri dari beberapa komponen inti, yaitu daftar dengan item. J dalam bentuk yang paling sederhana, dapat melakukan perjalanan ke seluruh dunia dan digunakan oleh semua orang. Pengguna yang diarahkan ke halaman ini dapat melihat daftar dan mengklik link untuk melihat item. Inilah markas kami yang mudah diakses.
Kirim 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
pada <img>
. Teks alternatif untuk media
adalah peluang UX untuk membantu memberikan konteks tambahan pada thumbnail, atau sebagai
teks pengganti jika gambar tidak dimuat, atau menyediakan UI lisan untuk pengguna
mengandalkan teknologi pendukung seperti
pembaca layar atau {i>screen reader<i}. Pelajari lebih lanjut dengan Five Golden
aturan untuk mematuhi alt
teks.
Atribut loading
menerima kata kunci lazy
sebagai cara untuk memberi sinyal gambar ini
sumber hanya boleh diambil bila gambar berada dalam area pandang. Dapat berupa
sangat bagus untuk daftar yang besar, karena pengguna hanya akan mengunduh gambar untuk item yang
di-scroll hingga terlihat.
Mendukung preferensi skema warna pengguna
Gunakan color-scheme
sebagai tag <meta>
untuk memberi tahu browser bahwa halaman Anda
menginginkan gaya agen pengguna terang dan gelap yang disediakan. Ini adalah mode gelap gratis
atau mode terang, tergantung bagaimana Anda melihatnya:
<meta name="color-scheme" content="dark light">
Tag meta memberikan sinyal sedini mungkin, sehingga browser dapat memilih warna kanvas default gelap jika pengguna memiliki preferensi tema gelap. Ini berarti bahwa navigasi antar laman situs tidak akan berkedip kanvas putih latar belakang antar-pemuatan. Tema gelap yang mulus di antara pemuatan, jauh lebih bagus di mata.
Pelajari lebih lanjut dari Thomas Steiner di https://web.dev/color-scheme/.
Menambahkan konten
Mengingat struktur konten ul > li > a > figure > picture > img
di atas,
tugas selanjutnya adalah menambahkan gambar
dan judul untuk di-scroll. Saya telah mengemas demo dengan
gambar dan teks placeholder statis, tetapi jangan ragu untuk memberdayakannya dari
sumber data favorit Anda.
Menambahkan gaya dengan CSS
Sekarang saatnya CSS mengambil daftar konten generik ini dan mengubahnya menjadi pengalaman yang lancar bagi developer. Netflix, App store, dan banyak situs serta aplikasi lainnya menggunakan horizontal area scroll untuk mengemas area pandang dengan kategori dan opsi.
Membuat tata letak scroller
Penting untuk menghindari pemotongan konten dalam tata letak atau bersandar pada teks potongan dengan elipsis. Banyak televisi memiliki scroller media seperti seperti ini, tetapi sering kali menggunakan penggunaan konten untuk dihapus. Tata letak ini tidak benar. Ini juga memungkinkan konten media mengganti ukuran kolom, membuat 1 tata letak cukup fleksibel untuk menangani banyak kombinasi menarik.
Penampung memungkinkan penggantian ukuran kolom dengan memberikan ukuran default sebagai properti khusus. Tata letak {i>grid<i} ini memiliki pandangan tentang ukuran kolom, hanya mengelola jarak 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 kustom kemudian digunakan oleh elemen <picture>
untuk membuat rasio aspek dasar: 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);
}
}
Hanya dengan beberapa gaya minor lainnya, selesaikan barebone 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 scroll dan navigasi keyboard
melalui daftarnya, maka setiap elemen <li>
turunan langsung akan menghapus ::marker
-nya
dengan mendapatkan jenis tampilan baru inline-block
.
Gambar belum responsif, dan langsung meledak mereka ada di dalamnya. Jinjikan mereka dengan beberapa ukuran, pas, dan gaya {i>border<i}, dan gradien latar belakang saat mereka menjalankan 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
Perataan dengan konten halaman, serta area permukaan scroll tepi-ke-tepi, sangat penting bagi komponen yang harmonis dan minimal.
Untuk mencapai tata letak scroll tepi-ke-tepi yang selaras dengan tipografi kita
dan garis tata letak, 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 scroll horizontal Hal di atas menunjukkan betapa mudahnya untuk menambahkan container scroll, tetapi ada masalah kompatibilitas yang belum terselesaikan (Namun, di Chromium 91+ telah diperbaiki!). Lihat di sini untuk sementara waktu riwayat tersebut, namun versi singkatnya adalah bahwa {i>padding<i} tidak selalu diperhitungkan dalam tampilan scroll.
Untuk mengelabui browser agar menempatkan padding di akhir scroller, saya akan menargetkan gambar terakhir dalam setiap daftar dan menambahkan elemen semu yang atau 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);
}
}
Penggunaan properti logis memungkinkan scroller media bekerja dalam mode penulisan apa pun dan arah dokumen.
Pengepasan scroll
Container scroll dengan overflow dapat menjadi area pandang yang tepat dengan satu baris CSS, lalu akan digunakan pada turunan untuk menentukan bagaimana mereka ingin menyejajarkan 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 luar biasa di TV, di App Store, dan banyak lagi. Banyak platform {i>video game<i} menggunakan scroller media dengan mirip dengan ini, sebagai tata letak layar beranda utama. Fokus adalah pengalaman UX yang besar di sini, bukan hanya tambahan kecil. Bayangkan menggunakan penggulir media dari sofa Anda dengan sebuah {i>remote<i}, berikan beberapa peningkatan kecil pada interaksi itu:
.horizontal-media-scroller a {
outline-offset: 12px;
&:focus {
outline-offset: 7px;
}
@media (prefers-reduced-motion: no-preference) {
& {
transition: outline-offset .25s ease;
}
}
}
Tindakan ini akan menyetel gaya garis batas fokus 7px
dari kotak, sehingga memberikan kesan
spasi. Jika pengguna tidak memiliki preferensi {i>motion <i}untuk mengurangi {i>motion, <i} {i>offset<i}
dialihkan, memberikan gerakan halus ke acara fokus.
Indeks keliling
Pengguna {i>gamepad<i} dan {i>keyboard<i} perlu perhatian khusus dalam daftar men-scroll konten dan opsi. Pola umum untuk menyelesaikan hal ini disebut indeks keliling. Ini adalah ketika penampung item difokuskan ke keyboard, tetapi hanya 1 turunan yang diizinkan untuk menyimpan 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 50+ waktu untuk mencapai akhir.
Ada 300 item di scroller pertama demo. Kami bisa melakukan lebih baik daripada membuat mereka akan melewati semuanya untuk mencapai bagian berikutnya.
Untuk membuat pengalaman ini, JavaScript perlu mengamati peristiwa keyboard dan fokus peristiwa. Saya membuat perpustakaan {i> open source<i} kecil di npm untuk membantu pengguna ini pengalaman yang mudah dicapai. Berikut cara menggunakannya untuk 3 scroller:
import {rovingIndex} from 'roving-ux';
rovingIndex({
element: someElement
});
Demo ini membuat kueri dokumen untuk scroller dan untuk masing-masing scroller akan memanggil
Fungsi rovingIndex()
. Teruskan elemen rovingIndex()
untuk mendapatkan penjelajahan
seperti container 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 kisi scroller media hanya menentukan arah dan spasi, ukuran bisa
di dalam kueri media, fitur yang memeriksa dukungan rasio aspek.
Progressive enhancement ke beberapa 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
ditingkatkan ke ukuran aspect-ratio
. Dengan menggunakan
{i>syntax<i} penyusunan bertingkat, setiap gambar
mengubah rasio aspeknya tergantung apakah baris pertama, kedua, atau ketiga. Tujuan
sintaksis nest juga memungkinkan penetapan beberapa
penyesuaian area pandang, di sana
bersama logika pengukuran lainnya.
Dengan CSS tersebut, karena fitur ini tersedia di lebih banyak mesin browser, pengalaman dikelola, tetapi tata letaknya akan lebih menarik secara visual.
Lebih memilih data yang dikurangi
Meskipun teknik berikutnya ini hanya tersedia
di belakang flag di
Canary,
Saya ingin berbagi bagaimana saya bisa 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 kondisi menyala
status data yang lebih rendah, seperti mode penghemat data. Jika ya, saya bisa memodifikasi
dokumen, dan dalam hal ini, menyembunyikan gambar.
figure {
@media (prefers-reduced-data: reduce) {
& {
min-inline-size: var(--size);
& > picture {
display: none;
}
}
}
}
Kontennya masih dapat dinavigasi tetapi tanpa biaya yang disertai dengan gambar yang berat
diunduh. 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 diambil pada tampilan layar yang lebar) tab browser ini, peningkatan pemuatan halaman sebesar ~80%, dan 10% data melalui kabel. CSS yang cukup canggih.
Kesimpulan
Sekarang setelah Anda tahu cara saya melakukannya, bagaimana Anda akan melakukannya?! 🙂
Mari kita diversifikasi pendekatan kami dan mempelajari semua cara untuk membangun di web. Buat Codepen atau host demo Anda sendiri, kirim tweet kepada saya, dan saya akan menambahkannya ke Bagian remix komunitas di bawah ini.
Sumber
Remix komunitas
Belum ada apa-apa di sini.