Ringkasan dasar tentang cara membangun komponen multi-pilihan yang responsif, adaptif, dan mudah diakses untuk mengurutkan dan memfilter pengalaman pengguna.
Dalam postingan ini saya ingin berbagi pemikiran tentang cara membangun komponen multi-pilihan. Mulai demo.
Jika Anda lebih suka menonton video, berikut versi YouTube untuk postingan ini:
Ringkasan
Pengguna sering kali diperlihatkan item, terkadang banyak item, dan dalam mungkin menjadi ide yang baik untuk menyediakan cara mengurangi daftar untuk mencegah pilihan berlebihan. Ini posting blog mengeksplorasi UI pemfilteran sebagai cara untuk mengurangi pilihan. Hal ini dilakukan dengan menampilkan atribut item yang dapat dipilih atau dibatalkan pengguna, sehingga mengurangi hasil dan karenanya mengurangi kelebihan pilihan.
Interaksi
Tujuannya adalah untuk memungkinkan traversal opsi filter yang cepat untuk semua pengguna dan
berbagai tipe input. Presentasi ini akan disampaikan dengan model
sepasang komponen. Sidebar tradisional kotak centang untuk desktop dan keyboard
dan pembaca layar, serta <select
multiple>
untuk pengguna sentuh.
Keputusan untuk menggunakan multi-pilihan bawaan untuk sentuhan, dan bukan untuk desktop, ini menghemat pekerjaan dan menciptakan pekerjaan, tetapi saya yakin memberikan pengalaman yang sesuai dengan lebih sedikit hutang kode daripada membangun seluruh pengalaman responsif dalam satu komponen.
Sentuh
Komponen sentuh menghemat ruang dan membantu akurasi interaksi pengguna pada
seluler. Cara ini menghemat ruang dengan menciutkan seluruh bilah sisi kotak centang menjadi
<select>
pengalaman sentuh overlay bawaan. Hal ini membantu akurasi
input dengan menunjukkan
pengalaman overlay sentuh besar yang
disediakan oleh sistem.
Keyboard dan gamepad
Di bawah ini adalah demonstrasi cara menggunakan <select multiple>
dari keyboard.
Multi-pilihan bawaan ini tidak dapat ditata dan hanya ditawarkan dalam model tidak cocok untuk menyajikan banyak pilihan. Lihat bagaimana Anda tidak bisa melihat luasnya pilihan di kotak kecil itu? Meskipun Anda dapat mengubah ukurannya, itu adalah masih belum dapat digunakan seperti bilah sisi kotak centang.
Markup
Kedua komponen akan dimuat dalam elemen <form>
yang sama. Hasil
formulir ini, baik kotak centang atau multi-pilihan, akan diamati dan digunakan untuk
menyaring kisi-kisi, tetapi juga
dapat dikirim ke server.
<form>
</form>
Komponen kotak centang
Kelompok kotak centang harus dikemas dalam satu
<fieldset>
dan diberi
<legend>
.
Ketika HTML disusun seperti ini, pembaca layar dan
FormData akan
secara otomatis memahami
hubungan elemen-elemen.
<form>
<fieldset>
<legend>New</legend>
… checkboxes …
</fieldset>
</form>
Setelah pengelompokan diterapkan, tambahkan <label>
dan <input type="checkbox">
untuk
masing-masing filter. Saya memilih untuk menggabungkannya di <div>
sehingga properti gap
CSS
dapat mengatur jaraknya secara merata dan mempertahankan keselarasan saat label multigaris.
<form>
<fieldset>
<legend>New</legend>
<div>
<input type="checkbox" id="last 30 days" name="new" value="last 30 days">
<label for="last 30 days">Last 30 Days</label>
</div>
<div>
<input type="checkbox" id="last 6 months" name="new" value="last 6 months">
<label for="last 6 months">Last 6 Months</label>
</div>
</fieldset>
</form>
<select multiple>
komponen
Fitur yang jarang digunakan dari elemen <select>
multiple
.
Jika atribut digunakan dengan elemen <select>
, pengguna akan diizinkan untuk
pilih banyak dari daftar. Ini seperti mengubah interaksi dari sebuah daftar radio
ke daftar kotak centang.
<form>
<select multiple="true" title="Filter results by category">
…
</select>
</form>
Untuk memberi label dan membuat grup di dalam <select>
, gunakan
<optgroup>
dan berikan atribut serta nilai label
. Elemen dan atribut ini
nilainya mirip dengan elemen <fieldset>
dan <legend>
.
<form>
<select multiple="true" title="Filter results by category">
<optgroup label="New">
…
</optgroup>
</select>
</form>
Sekarang tambahkan
<option>
elemen filter.
<form>
<select multiple="true" title="Filter results by category">
<optgroup label="New">
<option value="last 30 days">Last 30 Days</option>
<option value="last 6 months">Last 6 Months</option>
</optgroup>
</select>
</form>
Melacak input dengan penghitung untuk menginformasikan teknologi pendukung
Status
peran
digunakan dalam pengalaman pengguna ini, untuk melacak dan mempertahankan
filter untuk pembaca layar
dan teknologi bantuan lainnya. Video YouTube
mendemonstrasikan fitur tersebut. Integrasi dimulai dengan HTML dan atribut
role="status"
.
<div role="status" class="sr-only" id="applied-filters"></div>
Elemen ini akan membacakan dengan lantang perubahan yang dibuat pada konten. Kita dapat memperbarui konten dengan CSS penghitung saat pengguna berinteraksi dengan kotak centang. Untuk melakukan itu, pertama-tama kita perlu membuat dengan nama pada elemen induk dari input dan elemen status.
aside {
counter-reset: filters;
}
Secara default, jumlahnya adalah 0
, yang berarti tidak ada yang bernilai :checked
{i>default<i} dalam desain ini.
Selanjutnya, untuk menambah penghitung yang baru dibuat, kita akan menargetkan turunan dari
Elemen <aside>
yang merupakan :checked
. Saat pengguna mengubah
status input,
penghitung filters
akan dihitung.
aside :checked {
counter-increment: filters;
}
CSS kini mengetahui penghitungan umum UI kotak centang dan peran status
kosong dan menunggu nilai. Karena CSS mempertahankan penghitungan
memori,
counter()
memungkinkan pengaksesan nilai dari pseudo
elemen konten:
aside #applied-filters::before {
content: counter(filters) " filters ";
}
HTML untuk elemen peran status sekarang akan mengumumkan "2 filter " ke layar pembaca. Ini adalah awal yang baik, tetapi kita dapat melakukan yang lebih baik, seperti membagikan hasil hasil yang diperbarui oleh filter. Kita akan melakukan pekerjaan ini dari JavaScript, karena selain apa yang bisa dilakukan oleh penghitung.
Peningkatan antusiasme
Algoritma penghitung terasa hebat dengan CSS nesting-1, karena saya bisa menempatkan semua logika ke dalam satu blok. Terasa portabel dan terpusat untuk membaca dan memperbarui.
aside {
counter-reset: filters;
& :checked {
counter-increment: filters;
}
& #applied-filters::before {
content: counter(filters) " filters ";
}
}
Tata letak
Bagian ini menjelaskan tata letak antara kedua komponen tersebut. Sebagian besar gaya tata letak adalah untuk komponen kotak centang desktop.
Formulir
Untuk mengoptimalkan keterbacaan dan keterpindaian bagi pengguna, formulir diberi batas maksimum
30 karakter, pada dasarnya mengatur lebar garis optik untuk
label filter. Formulir ini menggunakan tata letak petak dan properti gap
untuk memberi jarak pada
{i>fieldset<i}.
form {
display: grid;
gap: 2ch;
max-inline-size: 30ch;
}
Elemen <select>
Daftar label dan kotak centang menggunakan terlalu banyak ruang di perangkat seluler. Oleh karena itu, tata letak akan memeriksa perubahan perangkat penunjuk utama pengguna pengalaman sentuhan.
@media (pointer: coarse) {
select[multiple] {
display: block;
}
}
Nilai coarse
menunjukkan bahwa pengguna tidak akan dapat berinteraksi dengan
layar dengan presisi tinggi
menggunakan perangkat input utama mereka. Pada
perangkat seluler, nilai pointer sering kali adalah coarse
, sebagai interaksi utama
adalah sentuhan. Di perangkat desktop, nilai pointer sering kali fine
seperti yang umum
menghubungkan {i>mouse<i} atau perangkat
input
presisi tinggi lainnya.
Kumpulan kolom
Gaya visual dan tata letak default <fieldset>
dengan <legend>
bersifat unik:
Biasanya, untuk memberi jarak elemen turunan, saya akan menggunakan properti gap
, tetapi
posisi <legend>
menyulitkan untuk membuat set yang berjarak sama
anak-anak. Bukan gap
, saudara yang berdekatan
pemilih dan
margin-block-start
digunakan.
fieldset {
padding: 2ch;
& > div + div {
margin-block-start: 2ch;
}
}
Tindakan ini akan meniadakan <legend>
penyesuaian ruang dengan menargetkan hanya
<div>
turunan.
Label dan kotak centang filter
Sebagai turunan langsung dari <fieldset>
dan dalam lebar maksimum formulir
30ch
, teks label dapat digabungkan jika terlalu panjang. Membungkus teks itu bagus, tapi
ketidaksejajaran antara teks dan kotak centang. Flexbox sangat cocok untuk hal ini.
fieldset > div {
display: flex;
gap: 2ch;
align-items: baseline;
}
Petak animasi
Animasi tata letak dilakukan oleh Isotope. J performa tinggi dan andal untuk pengurutan dan filter interaktif.
JavaScript
Selain membantu mengatur animasi yang rapi, kisi interaktif, JavaScript digunakan untuk memoles beberapa tepian.
Menormalkan input pengguna
Desain ini memiliki satu bentuk dengan dua cara berbeda untuk memberikan input, dan mereka Jangan melakukan serialisasi hal yang sama. Dengan beberapa JavaScript, kita bisa menormalisasi data.
Saya memilih untuk menyelaraskan struktur data elemen <select>
dengan kotak centang yang dikelompokkan
karena ada berbagai
struktur penetapan harga. Untuk melakukannya,
input
ditambahkan ke elemen <select>
. Pada titik ini,
selectedOptions
dipetakan.
document.querySelector('select').addEventListener('input', event => {
// make selectedOptions iterable then reduce a new array object
let selectData = Array.from(event.target.selectedOptions).reduce((data, opt) => {
// parent optgroup label and option value are added to the reduce aggregator
data.push([opt.parentElement.label.toLowerCase(), opt.value])
return data
}, [])
})
Sekarang Anda dapat mengirimkan formulir ini, atau dalam kasus demo ini, kirimkan petunjuk kepada Isotope pada apa yang harus difilter.
Menyelesaikan elemen peran status
Elemen hanya menghitung dan mengumumkan jumlah filter berdasarkan kotak centang
tetapi saya merasa itu adalah ide yang baik untuk juga berbagi jumlah
dan memastikan pilihan elemen <select>
juga dihitung.
Pilihan elemen <select>
tercermin dalam counter()
Di bagian normalisasi data, pemroses sudah dibuat pada input. Di akhir {i>function<i} ini jumlah filter yang dipilih dan jumlah hasil untuk filter tersebut diketahui. Nilai dapat diteruskan ke elemen peran status seperti ini.
let statusRoleElement = document.querySelector('#applied-filters')
statusRoleElement.style.counterSet = selectData.length
Hasil ditampilkan dalam elemen role="status"
:checked
menyediakan cara bawaan untuk meneruskan jumlah filter yang dipilih ke
elemen peran status, tetapi tidak memiliki visibilitas terhadap jumlah hasil yang difilter.
JavaScript dapat mengamati interaksi dengan kotak centang dan setelah memfilter
petak, tambahkan textContent
seperti yang dilakukan elemen <select>
.
document
.querySelector('aside form')
.addEventListener('input', e => {
// isotope demo code
let filterResults = IsotopeGrid.getFilteredItemElements().length
document.querySelector('#applied-filters').textContent = `giving ${filterResults} results`
})
Secara keseluruhan, pekerjaan ini menyelesaikan pengumuman "2 filter memberikan 25 hasil".
Sekarang pengalaman teknologi pendukung kami yang luar biasa akan dikirimkan ke semua pengguna, bagaimanapun mereka berinteraksi dengannya.
Kesimpulan
Sekarang setelah Anda tahu bagaimana saya melakukannya, bagaimana Anda akan 🙂
Mari kita diversifikasi pendekatan kami dan mempelajari semua cara untuk membangun di web. Buat demo, link tweet saya, dan saya akan menambahkannya ke bagian remix komunitas di bawah ini.
Remix komunitas
Belum ada apa-apa di sini.