Ringkasan dasar tentang cara membuat komponen breadcrumb yang responsif dan dapat diakses bagi pengguna untuk menjelajahi situs Anda.
Dalam postingan ini saya ingin berbagi pemikiran tentang cara membangun komponen breadcrumb. Coba demo.
Jika Anda lebih suka menonton video, berikut versi YouTube untuk postingan ini:
Ringkasan
Komponen breadcrumb menunjukkan posisi pengguna dalam hierarki situs. Namanya berasal dari Hansel dan Gretel, yang meletakkan breadcrumb di belakangnya di beberapa hutan gelap dan dapat menemukan jalan pulang dengan melacak remah-remah ke belakang.
Breadcrumb dalam postingan ini bukan breadcrumb standar, melainkan seperti breadcrumb. Library ini menawarkan fungsi tambahan dengan menempatkan halaman
seinduk langsung ke navigasi dengan <select>
, sehingga memungkinkan akses
multi-tingkat.
UX Latar Belakang
Dalam video demo komponen di atas, kategori placeholder adalah genre
video game. Jalur ini dibuat dengan menavigasi jalur berikut: home »
rpg » indie » on sale
, seperti yang ditunjukkan di bawah.
Komponen breadcrumb ini akan memungkinkan pengguna menjelajahi hierarki informasi ini; melompati cabang dan memilih halaman dengan cepat dan akurasi.
{i>Information architecture<i} (arsitektur informasi)
Menurut saya, memikirkan koleksi dan barang memberikan manfaat.
Koleksi
Koleksi adalah array opsi yang dapat dipilih. Dari halaman beranda prototipe breadcrumb pada postingan ini, koleksinya adalah FPS, RPG, brawler, dungeon crawler, sports, dan puzzle.
Item
Video game adalah item, koleksi tertentu juga dapat berupa item jika mewakili koleksi lainnya. Misalnya, RPG adalah item dan koleksi yang valid. Jika berupa item, pengguna akan berada di halaman koleksi tersebut. Misalnya, mereka berada di halaman RPG, yang menampilkan daftar game RPG, termasuk subkategori tambahan AAA, Indie, dan Dipublikasikan Sendiri.
Dalam istilah ilmu komputer, komponen breadcrumb ini merepresentasikan array multidimensi:
const rawBreadcrumbData = {
"FPS": {...},
"RPG": {
"AAA": {...},
"indie": {
"new": {...},
"on sale": {...},
"under 5": {...},
},
"self published": {...},
},
"brawler": {...},
"dungeon crawler": {...},
"sports": {...},
"puzzle": {...},
}
Aplikasi atau situs Anda akan memiliki arsitektur informasi (IA) kustom yang membuat array multidimensi yang berbeda, tetapi saya harap konsep halaman landing koleksi dan traversal hierarki juga dapat muncul dalam breadcrumb Anda.
Tata letak
Markup
Komponen yang baik dimulai dengan HTML yang sesuai. Pada bagian selanjutnya, saya akan membahas pilihan markup dan bagaimana pengaruhnya terhadap komponen keseluruhan.
Skema gelap dan terang
<meta name="color-scheme" content="dark light">
Tag meta color-scheme
dalam cuplikan di atas memberi tahu browser bahwa halaman ini menginginkan gaya browser terang dan gelap. Contoh breadcrumb tidak menyertakan CSS apa pun untuk skema warna ini,
sehingga breadcrumb akan menggunakan warna default yang disediakan oleh browser.
Elemen navigasi
<nav class="breadcrumbs" role="navigation"></nav>
Sebaiknya gunakan
elemen <nav>
untuk navigasi situs, yang memiliki peran navigasi ARIA implisit.
Dalam pengujian, saya melihat bahwa atribut role
mengubah cara
pembaca layar berinteraksi dengan elemen. Atribut tersebut sebenarnya diumumkan sebagai
navigasi, sehingga saya memilih untuk menambahkannya.
Ikon
Jika ikon diulang di halaman, dengan elemen
<use>
SVG
berarti Anda dapat menentukan path
sekali, dan menggunakannya untuk semua instance
ikon. Tindakan ini akan mencegah pengulangan informasi jalur yang sama, sehingga menyebabkan dokumen menjadi lebih besar dan potensi inkonsistensi jalur.
Untuk menggunakan teknik ini, tambahkan elemen SVG tersembunyi ke halaman dan gabungkan ikon
dalam elemen <symbol>
dengan ID unik:
<svg style="display: none;">
<symbol id="icon-home">
<title>A home icon</title>
<path d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"/>
</symbol>
<symbol id="icon-dropdown-arrow">
<title>A down arrow</title>
<path d="M19 9l-7 7-7-7"/>
</symbol>
</svg>
Browser membaca HTML SVG, memasukkan informasi ikon ke dalam memori, dan melanjutkan dengan bagian halaman lainnya yang mereferensikan ID untuk penggunaan ikon lainnya, seperti ini:
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<use href="#icon-home" />
</svg>
<svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
<use href="#icon-dropdown-arrow" />
</svg>
Tentukan sekali, gunakan sebanyak yang Anda inginkan, dengan dampak performa halaman minimal
dan gaya visual yang fleksibel. Perhatikan bahwa aria-hidden="true"
ditambahkan ke elemen SVG.
Ikon tidak berguna bagi seseorang yang menjelajah dan hanya mendengar konten, menyembunyikannya
dari pengguna tersebut akan menghentikan mereka menambahkan derau yang tidak perlu.
Link terpisah .crumb
Di sinilah breadcrumb tradisional dan breadcrumb di komponen ini berbeda.
Biasanya, link ini hanya akan menjadi link <a>
, tetapi saya telah menambahkan UX traversal dengan
pilihan yang disamarkan. Class .crumb
bertanggung jawab untuk menata letak link dan
ikon, sedangkan .crumbicon
bertanggung jawab untuk menumpuk ikon dan memilih
elemen secara bersamaan. Saya menyebutnya sebagai link terpisah karena fungsinya sangat
mirip dengan tombol-terpisah,
tetapi untuk navigasi halaman.
<span class="crumb">
<a href="#sub-collection-b">Category B</a>
<span class="crumbicon">
<svg>...</svg>
<select class="disguised-select" title="Navigate to another category">
<option>Category A</option>
<option selected>Category B</option>
<option>Category C</option>
</select>
</span>
</span>
Link dan beberapa opsi bukanlah hal yang istimewa, melainkan menambahkan lebih banyak fungsi ke breadcrumb sederhana. Menambahkan title
ke elemen <select>
berguna bagi pengguna pembaca
layar, sehingga memberi mereka informasi tentang tindakan tombol. Namun, cara ini
juga memberikan bantuan yang sama kepada orang lain, Anda akan melihatnya di bagian terdepan
di iPad. Satu atribut memberikan konteks tombol kepada banyak pengguna.
Dekorasi pemisah
<span class="crumb-separator" aria-hidden="true">→</span>
Pemisah bersifat opsional, menambahkan hanya satu juga dapat digunakan (lihat contoh ketiga dalam video
di atas). Kemudian, saya memberikan setiap aria-hidden="true"
karena bersifat dekoratif dan bukan
sesuatu yang perlu dibacakan oleh pembaca layar.
Properti gap
, yang dibahas berikutnya, membuat jaraknya menjadi mudah.
Gaya
Karena warna menggunakan warna sistem, sebagian besar warna merupakan celah dan tumpukan untuk gaya.
Arah dan alur tata letak
Elemen navigasi utama nav.breadcrumbs
menetapkan properti kustom cakupan
yang akan digunakan turunan, dan membuat tata letak horizontal
yang disejajarkan secara vertikal. Ini memastikan bahwa remah-remah, {i>divider<i}, dan ikon sejajar.
.breadcrumbs {
--nav-gap: 2ch;
display: flex;
align-items: center;
gap: var(--nav-gap);
padding: calc(var(--nav-gap) / 2);
}
Setiap .crumb
juga menetapkan tata letak horizontal yang disejajarkan secara vertikal dengan beberapa
celah, tetapi secara khusus menargetkan turunan tautannya dan menentukan gaya
white-space: nowrap
. Hal ini sangat penting untuk breadcrumb multi-kata karena kami tidak
ingin breadcrumb multi-baris. Nanti dalam postingan ini, kita akan menambahkan gaya untuk menangani
overflow horizontal yang disebabkan oleh properti white-space
ini.
.crumb {
display: inline-flex;
align-items: center;
gap: calc(var(--nav-gap) / 4);
& > a {
white-space: nowrap;
&[aria-current="page"] {
font-weight: bold;
}
}
}
aria-current="page"
ditambahkan untuk membantu link halaman saat ini tampil beda dari yang lain. Pengguna pembaca layar tidak hanya akan memiliki indikator yang jelas bahwa link tersebut
untuk halaman saat ini, kami juga telah menata gaya elemen secara visual untuk membantu pengguna yang dapat melihat
pengalaman pengguna yang serupa.
Komponen .crumbicon
menggunakan petak untuk menumpuk ikon SVG dengan elemen
<select>
yang "hampir tidak terlihat".
.crumbicon {
--crumbicon-size: 3ch;
display: grid;
grid: [stack] var(--crumbicon-size) / [stack] var(--crumbicon-size);
place-items: center;
& > * {
grid-area: stack;
}
}
Elemen <select>
berada di urutan terakhir dalam DOM, sehingga berada di atas tumpukan, dan interaktif. Tambahkan gaya opacity: .01
agar elemen masih dapat digunakan,
dan hasilnya adalah kotak pilihan yang sangat cocok dengan bentuk ikon.
Ini adalah cara yang bagus untuk menyesuaikan tampilan elemen <select>
sambil
mempertahankan fungsionalitas bawaan.
.disguised-select {
inline-size: 100%;
block-size: 100%;
opacity: .01;
font-size: min(100%, 16px); /* Defaults to 16px; fixes iOS zoom */
}
Tambahan
Breadcrumb harus bisa mewakili jejak yang sangat panjang. Saya suka membiarkan segala sesuatunya keluar dari layar secara horizontal, jika perlu, dan saya merasa komponen breadcrumb ini memenuhi syarat dengan baik.
.breadcrumbs {
overflow-x: auto;
overscroll-behavior-x: contain;
scroll-snap-type: x proximity;
scroll-padding-inline: calc(var(--nav-gap) / 2);
& > .crumb:last-of-type {
scroll-snap-align: end;
}
@supports (-webkit-hyphens:none) { & {
scroll-snap-type: none;
}}
}
Gaya tambahan menyiapkan UX berikut:
- Scroll horizontal dengan pembatasan overscroll.
- Padding scroll horizontal.
- Satu titik di remah terakhir. Ini berarti bahwa saat pemuatan halaman, pemuatan remah pertama dipaskan dan terlihat.
- Menghapus titik snap dari Safari, yang kesulitan dengan kombinasi efek snap dan scroll horizontal.
Kueri media
Satu penyesuaian kecil untuk area pandang yang lebih kecil adalah menyembunyikan label "Beranda", sehingga hanya menyisakan ikon:
@media (width <= 480px) {
.breadcrumbs .home-label {
display: none;
}
}
Aksesibilitas
Gerakan
Tidak ada banyak gerakan dalam komponen ini, tetapi dengan menggabungkan
transisi dalam pemeriksaan prefers-reduced-motion
, kita dapat mencegah gerakan yang tidak diinginkan.
@media (prefers-reduced-motion: no-preference) {
.crumbicon {
transition: box-shadow .2s ease;
}
}
Tidak ada gaya lain yang perlu diubah, efek pengarahan kursor dan fokus akan bagus dan bermakna tanpa transition
, tetapi jika gerakan dapat digunakan, kita akan menambahkan transisi halus
ke interaksi.
JavaScript
Pertama, apa pun jenis router yang Anda gunakan di situs atau aplikasi,
saat pengguna mengubah breadcrumb, URL perlu diperbarui dan pengguna
menampilkan halaman yang sesuai. Kedua, untuk menormalisasi pengalaman pengguna, pastikan
tidak ada navigasi yang tidak terduga yang terjadi saat pengguna hanya menjelajahi opsi
<select>
.
Dua tindakan penting pengalaman pengguna yang harus ditangani oleh JavaScript: select telah berubah dan pencegahan pengaktifan peristiwa perubahan <select>
yang cepat.
Pencegahan peristiwa yang segera diperlukan karena penggunaan elemen
<select>
. Di Windows Edge, dan mungkin browser lain juga, peristiwa changed
yang dipilih akan diaktifkan saat pengguna menjelajahi opsi dengan keyboard. Inilah alasan saya
menyebutnya bersemangat karena pengguna hanya memilih opsi semu, seperti pengarahan kursor
atau fokus, tetapi belum mengonfirmasi pilihan dengan enter
atau click
. Peristiwa
yang bersemangat membuat fitur perubahan kategori komponen ini tidak dapat diakses karena
membuka kotak pilihan dan sekadar menjelajahi item akan mengaktifkan peristiwa dan
mengubah halaman, sebelum pengguna siap.
Perubahan peristiwa <select>
yang lebih baik
const crumbs = document.querySelectorAll('.breadcrumbs select')
const allowedKeys = new Set(['Tab', 'Enter', ' '])
const preventedKeys = new Set(['ArrowUp', 'ArrowDown'])
// watch crumbs for changes,
// ensures it's a full value change, not a user exploring options via keyboard
crumbs.forEach(nav => {
let ignoreChange = false
nav.addEventListener('change', e => {
if (ignoreChange) return
// it's actually changed!
})
nav.addEventListener('keydown', ({ key }) => {
if (preventedKeys.has(key))
ignoreChange = true
else if (allowedKeys.has(key))
ignoreChange = false
})
})
Strateginya adalah memantau peristiwa saat keyboard menurun pada setiap elemen <select>
dan menentukan apakah tombol yang ditekan adalah konfirmasi navigasi (Tab
atau
Enter
) atau navigasi spasial (ArrowUp
atau ArrowDown
). Dengan penentuan
ini, komponen dapat memutuskan untuk menunggu atau berhenti, saat peristiwa untuk
elemen <select>
diaktifkan.
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.
Remix komunitas
- Tux Solbakk sebagai komponen web: demo dan kode