Menggunakan alur pembacaan CSS untuk navigasi fokus berurutan yang logis

Dipublikasikan: 1 Mei 2025

Properti reading-flow dan reading-order CSS tersedia mulai Chrome 137. Postingan ini menjelaskan alasan di balik desain properti ini dan beberapa detail singkat untuk membantu Anda memulainya.

Metode tata letak seperti petak dan fleksibel telah mengubah pengembangan frontend, tetapi fleksibilitasnya dapat menyebabkan masalah bagi beberapa pengguna. Sangat mudah untuk membuat situasi saat urutan visual tidak cocok dengan urutan sumber dalam hierarki DOM. Karena urutan sumber ini adalah yang diikuti browser jika Anda menjelajahi situs menggunakan keyboard, beberapa pengguna dapat mengalami lompatan yang tidak terduga saat mereka membuka halaman.

Properti reading-flow dan reading-order telah dirancang dan ditambahkan ke spesifikasi Layar CSS, untuk mencoba menyelesaikan masalah yang sudah lama ini.

reading-flow

Properti CSS reading-flow mengontrol urutan elemen dalam tata letak flex, petak, atau blok yang ditampilkan ke alat aksesibilitas dan cara elemen tersebut difokuskan menggunakan metode navigasi berurutan linear.

Kode ini memerlukan satu nilai kata kunci, dengan default normal, yang mempertahankan perilaku pengurutan elemen dalam urutan DOM. Untuk menggunakannya di dalam penampung fleksibel, tetapkan nilainya ke flex-visual atau flex-flow. Untuk menggunakannya di dalam penampung petak, tetapkan nilainya ke grid-rows, grid-columns, atau grid-order.

reading-order

Properti CSS reading-order memungkinkan Anda mengganti urutan item secara manual dalam penampung alur membaca. Untuk menggunakan properti ini di dalam penampung petak, flex, atau blok, tetapkan nilai reading-flow pada penampung ke source-order dan tetapkan reading-order setiap item ke nilai bilangan bulat.

Contoh di flexbox

Misalnya, Anda mungkin memiliki penampung tata letak fleksibel dengan tiga elemen dalam urutan baris terbalik, dan juga ingin menggunakan properti urutan untuk mengacak ulang urutan tersebut.

<div class="box">
 <a href="#">One</a>
 <a href="#">Two</a>
 <a href="#">Three</a>
</div>
.box {
  display: flex;
  flex-direction: row-reverse;
}

.box :nth-child(1) {
  order: 2;
}

Anda dapat mencoba menavigasi elemen ini menggunakan tombol TAB untuk menemukan elemen berikutnya yang dapat difokuskan dan tombol TAB+SHIFT untuk menemukan elemen sebelumnya yang dapat difokuskan. Ini mengikuti item dalam urutan sumber: Satu, Dua, Tiga.

Dari sudut pandang pengguna akhir, hal ini tidak masuk akal dan dapat sangat membingungkan. Hal yang sama terjadi jika kita menggunakan alat navigasi ruang aksesibilitas untuk menavigasi seluruh halaman.

Untuk memperbaikinya, tetapkan properti reading-flow:

.box {
  reading-flow: flex-visual;
}

Urutan fokus sekarang adalah: Satu, Tiga, Dua. Hal ini sama dengan urutan visual yang akan Anda dapatkan jika membaca dalam bahasa Inggris dari kiri ke kanan.

Jika Anda lebih memilih untuk mempertahankan urutan fokus seperti yang dimaksudkan awalnya, dalam urutan terbalik, Anda dapat menetapkan:

.box {
  reading-flow: flex-flow;
}

Urutan fokus kini menjadi urutan fleksibel terbalik: Dua, Tiga, Satu. Dalam kedua kasus tersebut, properti order CSS diperhitungkan.

Contoh dengan tata letak petak

Untuk melihat cara kerjanya dalam petak, bayangkan Anda membuat tata letak dengan item yang ditempatkan otomatis grid CSS dengan dua belas area yang dapat difokuskan.

<div class="wrapper">
 <a href="#">One</a>
 <a href="#">Two</a>
 <a href="#">Three</a>
 <a href="#">Four</a>
 <a href="#">Five</a>
 <a href="#">Six</a>
 <a href="#">Seven</a>
 <a href="#">Eight</a>
 <a href="#">Nine</a>
 <a href="#">Ten</a>
 <a href="#">Eleven</a>
 <a href="#">Twelve</a>
</div>

Anda ingin turunan kelima menempati ruang terbesar di bagian paling atas, diikuti dengan turunan kedua di bagian tengah petak. Semua turunan lainnya dapat ditempatkan secara otomatis dalam petak mengikuti template kolom.

.wrapper {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 100px;
}
.wrapper a:nth-child(2) {
  grid-column: 3;
  grid-row: 2 / 4;
}
.wrapper a:nth-child(5) {
  grid-column: 1 / 3;
  grid-row: 1 / 3;
}

Coba buka elemen ini menggunakan tombol TAB untuk menemukan elemen berikutnya yang dapat difokuskan dan tombol TAB+SHIFT untuk menemukan elemen sebelumnya yang dapat difokuskan. Ini mengikuti item dalam urutan sumber: Satu hingga Dua Belas.

Untuk memperbaikinya, tetapkan properti reading-flow:

.wrapper {
  reading-flow: grid-rows;
}

Urutan fokus sekarang adalah: Lima, Satu, Tiga, Dua, Empat, Enam, Tujuh, Delapan, Sembilan, Sepuluh, Sebelas, Dua Belas. Urutan ini mengikuti urutan visual, baris demi baris.

Jika ingin alur bacaan mengikuti urutan kolom, Anda dapat menggunakan nilai kata kunci grid-columns. Urutan fokus kemudian menjadi Lima, Enam, Sembilan, Tujuh, Sepuluh, Satu, Dua, Sebelas, Tiga, Empat, Delapan, Dua Belas.

.wrapper {
  reading-flow: grid-columns;
}

Anda juga dapat mencoba menggunakan grid-order. Urutan fokus tetap Satu hingga Dua Belas. Hal ini karena tidak ada urutan CSS yang ditetapkan pada item apa pun.

Penampung blok menggunakan reading-order

Dengan properti reading-order, Anda dapat menentukan kapan dalam alur membaca item harus dikunjungi, yang mengganti urutan yang ditetapkan oleh properti reading-flow. Hal ini hanya berlaku pada penampung alur membaca yang valid, jika properti reading-flow bukan normal.

.wrapper {
  display: block;
  reading-flow: source-order;
}

.top {
  reading-order: -1;
  inset-inline-start: 50px;
  inset-block-start: 50px;
}

Penampung blok berikut berisi lima item. Tidak ada aturan tata letak yang mengurutkan ulang elemen dari urutan sumbernya, tetapi ada satu item di luar alur yang harus dikunjungi terlebih dahulu.

<div class="wrapper">
  <a href="#">Item 1</a>
  <a href="#">Item 2</a>
  <a href="#">Item 3</a>
  <a href="#">Item 4</a>
  <a class="top" href="#">Item 5</a>
</div>

Dengan menetapkan reading-order item ini ke -1, urutan fokus akan mengunjunginya terlebih dahulu sebelum kembali ke urutan sumber untuk item alur membaca lainnya.

Anda dapat menemukan contoh lainnya di situs chrome.dev.

Interaksi dengan tabindex

Secara historis, developer telah menggunakan atribut global tabindex HTML untuk membuat elemen HTML dapat difokuskan dan menentukan pengurutan relatif untuk navigasi fokus berurutan. Namun, atribut ini memiliki banyak kelemahan dan masalah aksesibilitas. Masalah utamanya adalah navigasi fokus yang diurutkan tabindex yang dibuat menggunakan tabindex positif tidak dikenali oleh hierarki aksesibilitas. Jika tidak digunakan dengan benar, Anda mungkin akan mendapatkan urutan fokus yang tidak stabil yang tidak cocok dengan pengalaman di pembaca layar. Untuk memperbaikinya, lacak pengurutan menggunakan atribut HTML aria-owns.

Dalam contoh fleksibel sebelumnya, untuk mendapatkan hasil yang sama seperti menggunakan reading-flow: flex-visual, Anda dapat melakukan hal berikut.

<div class="box" aria-owns="one three two">
  <a href="#" tabindex="1" id="one">One</a>
  <a href="#" tabindex="3" id="two">Two</a>
  <a href="#" tabindex="2" id="three">Three</a>
</div>

Namun, apa yang terjadi jika elemen lain di luar penampung juga memiliki tabindex=1? Kemudian, semua elemen dengan tabindex=1 akan dikunjungi bersama, sebelum kita beralih ke nilai tabindex inkremental berikutnya. Navigasi berurutan yang melompat-lompat ini akan menghasilkan pengalaman pengguna yang buruk. Oleh karena itu, pakar aksesibilitas menyarankan untuk menghindari tabindex positif. Kami mencoba memperbaikinya saat mendesain reading-flow.

Penampung yang memiliki kumpulan properti reading-flow akan menjadi pemilik cakupan fokus. Ini berarti cakupan navigasi fokus berurutan untuk mengunjungi setiap elemen di dalam penampung sebelum berpindah ke elemen berikutnya yang dapat difokuskan dalam dokumen web. Selain itu, turunan langsungnya diurutkan menggunakan properti alur bacaan dan tabindex positif diabaikan untuk tujuan pengurutan. Anda masih dapat menetapkan tabindex positif pada turunan item alur membaca.

Perhatikan bahwa elemen dengan display: contents yang mewarisi properti reading-flow dari induk tata letaknya juga akan menjadi penampung alur pembacaan yang valid. Perhatikan hal ini saat mendesain situs Anda. Baca selengkapnya tentang hal ini dalam permintaan kami untuk masukan tentang reading-flow dan display: contents.

Beri tahu kami

Coba contoh dalam postingan ini dan dalam contoh reading-flow di chrome.dev, dan gunakan properti CSS ini di situs Anda. Jika Anda memiliki masukan, ajukan sebagai masalah di repositori GitHub CSS Working Group. Jika Anda memiliki masukan khusus tentang tabindex dan perilaku cakupan fokus, ajukan sebagai masalah pada repo GitHub HTML WHATNOT. Kami ingin mendengar masukan Anda terkait fitur ini.