Memodifikasi urutan DOM dengan tabindex
Urutan tab default yang disediakan oleh posisi DOM elemen native cukup praktis, namun ada kalanya Anda ingin mengubah urutan tab, dan memindahkan elemen secara fisik di HTML tidak selalu merupakan solusi yang optimal atau bahkan layak. Untuk kasus ini, Anda dapat menggunakan atribut HTML tabindex
untuk
menetapkan posisi tab elemen secara eksplisit.
tabindex
dapat diterapkan ke elemen apa pun - meskipun tidak selalu
berguna pada setiap elemen - dan menggunakan rentang nilai bilangan bulat. Dengan
tabindex
, Anda dapat menentukan urutan eksplisit untuk elemen halaman yang dapat difokuskan,
menyisipkan elemen yang tidak dapat difokuskan ke dalam urutan tab, dan menghapus elemen
dari urutan tab. Contoh:
tabindex="0"
: Menyisipkan elemen ke dalam urutan tab alami. Elemen dapat
difokus dengan menekan tombol Tab
, dan elemen dapat difokuskan dengan memanggil
metode focus()
-nya
<custom-button tabindex="0">Press Tab to Focus Me!</custom-button>
tabindex="-1"
: Menghapus elemen dari urutan tab alami, tetapi elemen
masih dapat difokuskan dengan memanggil metode focus()
// TODO: DevSite - Code sample removed as it used inline event handlers
// TODO: DevSite - Contoh kode dihapus karena menggunakan pengendali peristiwa inline
tabindex="5"
: Setiap tabindex yang lebih besar dari 0 akan melompatkan elemen ke depan
urutan tab alami. Jika ada beberapa elemen dengan tabindex lebih besar dari 0, urutan tab akan dimulai dari nilai terendah yang lebih besar dari nol dan akan terus naik. Menggunakan tabindex yang lebih besar dari 0 dianggap sebagai
anti-pola.
<button>I should be first</button>
<button>And I should be second</button>
<button tabindex="5">But I jumped to the front!</button>
Hal ini khususnya berlaku untuk elemen non-input seperti header, gambar, atau judul
artikel. Menambahkan tabindex
ke jenis elemen tersebut bersifat kontraproduktif. Jika
memungkinkan, sebaiknya atur kode sumber Anda agar urutan DOM menyediakan
urutan tab yang logis. Jika Anda menggunakan tabindex
, batasi ke kontrol interaktif kustom
seperti tombol, tab, dropdown, dan kolom teks; yaitu, elemen
yang mungkin diharapkan pengguna untuk memberikan input.
Jangan khawatir pengguna pembaca layar akan kehilangan konten penting karena
tidak memiliki tabindex
. Meskipun konten itu sangat penting, seperti gambar,
jika konten bukanlah sesuatu yang dapat berinteraksi dengan pengguna, tidak ada alasan untuk membuatnya
dapat difokuskan. Pengguna pembaca layar tetap dapat memahami konten gambar selama
Anda memberikan dukungan atribut alt
yang sesuai, yang akan segera kami bahas.
Mengelola fokus di tingkat halaman
Berikut adalah skenario di mana tabindex
tidak hanya berguna, tetapi juga diperlukan. Anda mungkin
membangun satu halaman yang efektif dengan berbagai bagian konten, tidak semuanya
terlihat secara bersamaan. Di halaman semacam ini, mengklik link navigasi dapat mengubah konten yang terlihat tanpa memuat ulang halaman.
Jika ini terjadi, Anda mungkin akan mengidentifikasi area konten yang dipilih, memberinya
tabindex
dari -1 sehingga tidak muncul dalam urutan tab yang alami, dan
memanggil metode focus
-nya. Teknik ini, yang disebut mengelola fokus, membuat
konteks yang dirasakan pengguna tetap sinkron dengan konten visual situs.
Mengelola fokus dalam komponen
Mengelola fokus saat Anda mengubah sesuatu di halaman itu penting, tetapi terkadang Anda perlu mengelola fokus di tingkat kontrol — misalnya, jika Anda membuat komponen kustom.
Pertimbangkan elemen select
native. Elemen ini dapat menerima fokus dasar, tetapi setelah
ada, Anda dapat menggunakan tombol panah untuk menampilkan fungsi tambahan (opsi yang dapat dipilih). Jika mem-build elemen select
kustom, Anda mungkin
ingin mengekspos jenis perilaku yang sama ini sehingga pengguna yang terutama mengandalkan
keyboard masih dapat berinteraksi dengan kontrol Anda.
<!-- Focus the element using Tab and use the up/down arrow keys to navigate -->
<select>
<option>Aisle seat</option>
<option>Window seat</option>
<option>No preference</option>
</select>
Mungkin sulit mengetahui perilaku keyboard mana yang akan diterapkan, tetapi ada dokumen bermanfaat yang dapat Anda pelajari. Panduan Praktik Penulisan Aplikasi Internet Kaya yang Dapat Diakses (ARIA) mencantumkan jenis komponen dan jenis tindakan keyboard yang didukung. Kita akan membahas ARIA secara lebih detail nanti, tetapi untuk saat ini, mari kita gunakan panduan ini untuk membantu kita menambahkan dukungan keyboard ke komponen baru.
Mungkin Anda sedang mengerjakan beberapa Elemen Kustom baru yang menyerupai sekumpulan tombol pilihan, tetapi dengan tampilan dan perilaku yang unik.
<radio-group>
<radio-button>Water</radio-button>
<radio-button>Coffee</radio-button>
<radio-button>Tea</radio-button>
<radio-button>Cola</radio-button>
<radio-button>Ginger Ale</radio-button>
</radio-group>
Untuk menentukan jenis dukungan keyboard yang mereka butuhkan, Anda dapat melihat Panduan Praktik Penulisan ARIA. Bagian 2 berisi daftar pola desain, dan dalam daftar tersebut terdapat tabel karakteristik untuk grup radio, komponen yang ada dan paling cocok dengan elemen baru.
Seperti yang dapat Anda lihat pada tabel, salah satu perilaku keyboard umum yang harus didukung adalah tombol panah atas/bawah/kiri/kanan. Untuk menambahkan perilaku ini ke komponen baru, kita akan menggunakan teknik yang disebut roving tabindex.
Roving tabindex berfungsi dengan menetapkan tabindex
ke -1 untuk semua turunan kecuali yang saat ini aktif.
<radio-group>
<radio-button tabindex="0">Water</radio-button>
<radio-button tabindex="-1">Coffee</radio-button>
<radio-button tabindex="-1">Tea</radio-button>
<radio-button tabindex="-1">Cola</radio-button>
<radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>
Komponen ini kemudian menggunakan pemroses peristiwa keyboard untuk menentukan tombol mana
yang ditekan pengguna; saat ini terjadi, komponen akan menyetel tabindex
turunan
yang sebelumnya difokuskan ke -1, menetapkan tabindex
turunan yang akan difokuskan ke 0, dan memanggil
metode fokus di dalamnya.
<radio-group>
// Assuming the user pressed the down arrow, we'll focus the next available child
<radio-button tabindex="-1">Water</radio-button>
<radio-button tabindex="0">Coffee</radio-button> // call .focus() on this element
<radio-button tabindex="-1">Tea</radio-button>
<radio-button tabindex="-1">Cola</radio-button>
<radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>
Saat pengguna mencapai turunan terakhir (atau yang pertama, bergantung pada arah mereka memindahkan fokus), Anda akan memutar balik dan memfokuskan kembali turunan pertama (atau terakhir).
Anda dapat mencoba contoh yang sudah selesai di bawah ini. Periksa elemen di DevTools untuk mengamati pergerakan tabindex dari satu tombol radio ke tombol berikutnya.
// TODO: DevSite - Contoh kode dihapus karena menggunakan pengendali peristiwa inline
Anda dapat melihat sumber lengkap elemen ini di GitHub.
Modal dan perangkap keyboard
Terkadang saat mengelola fokus, Anda bisa masuk ke situasi yang tidak bisa Anda tinggalkan. Pertimbangkan widget pelengkapan otomatis yang mencoba mengelola fokus dan merekam perilaku tab, tetapi mencegah pengguna keluar dari widget hingga selesai. Hal ini disebut jebakan keyboard, dan bisa sangat menjengkelkan bagi pengguna. Bagian 2.1.2 dari checklist tampil di web untuk mengatasi masalah ini, yang menyatakan bahwa fokus keyboard tidak boleh terkunci atau terjebak pada satu elemen halaman tertentu. Pengguna harus dapat menavigasi ke dan dari semua elemen halaman hanya dengan menggunakan keyboard.
Aneh, ada kalanya perilaku ini benar-benar diinginkan, seperti di jendela modal. Biasanya, saat modal ditampilkan, Anda tidak ingin pengguna mengakses konten di belakangnya. Anda dapat menambahkan overlay untuk menutupi halaman secara visual, tetapi hal tersebut tidak menghentikan fokus keyboard keluar dari modal secara tidak sengaja.
Dalam kasus seperti ini, Anda dapat mengimplementasikan perangkap keyboard sementara untuk memastikan bahwa Anda menangkap fokus hanya saat modal ditampilkan, lalu memulihkan fokus ke item yang sebelumnya difokuskan saat modal ditutup.
Ada beberapa proposal tentang cara mempermudah developer, termasuk elemen
<dialog>
, tetapi mereka belum mendapatkan dukungan browser yang luas.Lihat artikel MDN ini untuk informasi selengkapnya tentang
<dialog>
, dan contoh modal ini untuk informasi selengkapnya tentang jendela modal.
Pertimbangkan dialog modal yang direpresentasikan oleh div
yang berisi beberapa elemen, dan
div
lain yang mewakili overlay latar belakang. Mari kita pelajari langkah-langkah dasar yang
diperlukan untuk menerapkan perangkap keyboard sementara dalam situasi ini.
- Dengan
document.querySelector
, pilih div modal dan overlay, serta simpan referensinya. - Saat modal terbuka, simpan referensi ke elemen yang difokuskan saat modal dibuka sehingga Anda dapat mengembalikan fokus ke elemen tersebut.
- Gunakan pemroses keydown untuk mengambil tombol saat ditekan saat modal terbuka. Anda juga dapat memproses klik di overlay latar belakang, dan menutup modal jika pengguna mengkliknya.
- Selanjutnya, dapatkan kumpulan elemen yang dapat difokuskan dalam modal. Elemen pertama dan terakhir yang dapat difokuskan akan bertindak sebagai "sentinel" untuk memberi tahu Anda kapan harus melakukan loop fokus ke depan atau ke belakang agar tetap berada di dalam modal.
- Menampilkan jendela modal dan memfokuskan elemen pertama yang dapat difokuskan.
- Saat pengguna menekan
Tab
atauShift+Tab
, pindahkan fokus ke depan atau ke belakang, dengan melakukan loop pada elemen terakhir atau pertama yang sesuai. - Jika pengguna menekan
Esc
, tutup modal. Hal ini sangat membantu karena memungkinkan pengguna menutup modal tanpa mencari tombol tutup tertentu, dan hal ini menguntungkan bahkan bagi pengguna yang menggunakan mouse. - Saat modal ditutup, sembunyikan overlay dan overlay latar belakang, serta pulihkan fokus ke elemen yang sebelumnya difokuskan dan telah disimpan sebelumnya.
Prosedur ini memberi Anda jendela modal yang dapat digunakan dan tidak mengecewakan, yang dapat digunakan semua orang secara efektif.
Untuk mengetahui detail selengkapnya, Anda dapat memeriksa kode contoh ini, dan melihat contoh langsung dari halaman lengkap.