Properti CSS appearance: base-select memungkinkan penataan gaya elemen <select> dan pemilihnya (melalui ::picker(select)) seperti elemen HTML biasa.
Jika digabungkan dengan teknik tata letak CSS modern seperti Grid atau Flexbox, Anda dapat beralih dari daftar vertikal bertumpuk tradisional dan menciptakan pengalaman visual yang kaya tanpa JS kustom.
Misalnya, Anda dapat menggunakan display: grid untuk menata gaya opsi sebagai petak kartu 2D.
Hal ini ideal untuk pemilih warna, pemilih emoji, atau varian produk yang menu visual lengkapnya lebih efektif daripada daftar.
Cara Menerapkan
1. Mengaktifkan Gaya Dasar
Terapkan appearance: base-select ke elemen <select> dan pseudo-elemen pemilih internalnya select::picker(select):
select.grid-picker {
&, &::picker(select) {
appearance: base-select;
}
}
2. Menata Gaya Penampung Pemilih
Targetkan select:open::picker(select) dan terapkan display: grid (atau display: flex).
Tentukan kolom dan celah seperti yang Anda lakukan untuk penampung apa pun.
select.grid-picker:open::picker(select) {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
PENTING: :open diperlukan. Jika Anda menata gaya select::picker(select), pemilih akan terlihat bahkan saat pilihan ditutup.
3. Menata Gaya Opsi
Targetkan elemen <option> untuk menata gayanya sebagai item petak atau kartu.
Anda dapat menambahkan gambar, SVG, atau tata letak yang kompleks di dalamnya.
/* Style options as grid cards */
.grid-picker option {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* padding, border-radius, background, etc. */
}
4. Menata gaya opsi yang dipilih
Untuk menata gaya opsi yang dipilih, gunakan option:checked. Contoh:
.grid-picker option:checked {
position: relative;
border: 2px solid var(--primary-color);
background-color: oklab(from var(--primary-color) l a b / 8%);
}
Seperti kontrol UI lainnya, jangan mengomunikasikan status hanya dengan warna, dan gunakan beberapa indikator visual (misalnya, warna, ketebalan batas, tanda centang) untuk mengomunikasikan opsi yang dipilih.
5. (Opsional) Menata gaya tanda centang opsi yang dipilih
Secara default, browser merender tanda centang sebagai turunan pertama dari setiap <option>.
Elemen ini berperilaku seperti ::before dengan content: "✓" / "", yang dirender sebelum ::before yang disediakan penulis, jika ada.
Jika opsi tidak dipilih, tanda centang akan disembunyikan melalui visibility: hidden.
Anda dapat menata gayanya menggunakan elemen pseudo ::checkmark, atau menyembunyikannya sepenuhnya jika Anda ingin menyampaikan pilihan melalui gaya saja atau menggunakan indikator kustom.
Misalnya, untuk menempatkannya di pojok kanan atas opsi, Anda dapat melakukan hal seperti:
select.grid-picker {
> option::checkmark {
/* Hide the checkmark for unselected options */
display: none;
}
> option:checked {
position: relative;
&::checkmark {
position: absolute;
inset-block-start: -.4em;
inset-inline-end: -.5em;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
min-inline-size: 1.6em;
aspect-ratio: 1;
padding-right: 0.12em;
padding-left: 0.05em;
border-radius: 50%;
background: var(--primary-color);
color: white;
font-size: 70%;
font-weight: bold;
}
}
}
Tips: Saat menggambar penampung (misalnya lingkaran) di sekitar tanda centang, geser sedikit ke atas (seperti yang kami lakukan di sini dengan padding-bottom dan padding-left) untuk pemusatan optik yang memperhitungkan bentuknya.
JANGAN gunakan padding-inline-start atau padding-block-end untuk ini, karena keduanya akan berubah bergantung pada mode penulisan, sedangkan bentuk tanda centang tidak.
6. (Opsional) Menyesuaikan tampilan opsi yang dipilih
Secara default, <select> akan menampilkan versi khusus teks dari opsi yang dipilih.
Untuk menampilkan konten lengkap untuk nilai yang dipilih, gunakan <selectedcontent> di dalam <button> dan/atau untuk menampilkan opsi yang dipilih secara berbeda (misalnya, menyembunyikan detail tertentu).
TIDAK menggunakan <selectedcontent> tanpa <button> di sekitarnya, karena <selectedcontent> hanya akan menjadi bagian dari pemilih, seperti elemen konten lainnya.
Praktik terbaik
- Menguji perilaku tata letak. Menetapkan
appearance: base-selectakan menghapus perilaku browser default yang mengubah ukuran pilihan berdasarkan lebar opsi terpanjangnya. Anda mungkin perlu menetapkan lebar tetap atau menggunakan batasan flex/grid untuk mencegah pergeseran tata letak. - Pastikan
<select>Anda memiliki atributnamedan<label>terkait. Hal ini memastikan bahwa meskipun dengan UI kustom, komponen tetap dapat diakses oleh pembaca layar dan berfungsi dengan benar dengan pengiriman formulir standar. - Gunakan atribut
valuestandar pada opsi untuk memastikan pengiriman formulir berfungsi sama persis seperti sebelumnya.
Aksesibilitas
<select> native hanya menangani navigasi panah Atas/Bawah linear, sehingga Kiri/Kanan tidak melakukan apa pun di pemilih yang terbuka dan Atas/Bawah masih menavigasi item secara berurutan, terlepas dari baris dan kolom.
Untuk menerapkan navigasi spasial yang mengikuti petak, Anda dapat mengintersepsi keydown dan mengarahkan fokus ke opsi terdekat dalam arah yang ditekan (misalnya, menggunakan getBoundingClientRect()) saat tombol panah digunakan.
Untuk menentukan item berikutnya/sebelumnya yang sesuai, gunakan metode DOM yang beroperasi pada geometri sebenarnya (misalnya getBoundingClientRect()), bukan mengurai string CSS seperti grid-template-columns atau grid-column, yang dapat rapuh dan rentan error untuk petak kompleks, subpetak, RTL, dan skenario tata letak lainnya.
Meskipun demikian, jangan terlalu merekayasa; gunakan invarian yang Anda ketahui benar tentang tata letak untuk menyederhanakan logika ini.
Catatan: Hal ini hanya membahas navigasi keyboard. <select> dan ::picker()-nya masih memiliki peran default (menu atau listbox), dan peran ini tidak dapat diganti, serta tidak diizinkan untuk berisi elemen dengan role="grid".
Menyusun bertingkat wrapper dengan role="grid" di dalam pemilih berfungsi dalam praktiknya, tetapi tidak valid, dan dapat mengejutkan pengguna AT.
Dalam beberapa kasus, penggunaan <optgroup> untuk mengelompokkan opsi dapat menghasilkan UX pembaca layar yang baik tanpa role="grid".
Jika tidak, pada akhirnya Anda mungkin perlu beralih ke solusi kustom menggunakan popover API, pemosisian anchor, dan role="grid" untuk mencapai UX yang diinginkan bagi pengguna pembaca layar.
Strategi Penggantian
Penggantian & dukungan browser untuk <select> yang Dapat Disesuaikan
Untuk browser yang belum mendukung appearance: base-select, elemen <select> akan menurun secara halus menjadi dropdown sistem operasi standar.
- Konten Non-Teks Diabaikan: Browser lama menghapus tag HTML (seperti
<svg>atau<div>) di dalam tag<option>dan hanya merender node teks. Pastikan konten teks<option>dapat dibaca dan bermakna dengan sendirinya. - Penanganan Struktur HTML: Parser standar dapat mengabaikan tag
<button>dan<selectedcontent>di dalam<select>atau memperlakukannya sebagai tidak valid. Polyfill JavaScript yang berat tidak mutlak diperlukan untuk progressive enhancement jika Anda menganggap teks standar sebagai pengganti yang dapat dibaca.
document.addEventListener("DOMContentLoaded", () => {
// Check if browser supports base-select value
if (!CSS.supports("appearance", "base-select")) {
// Custom select overrides are not supported natively.
}
});