Section Tables mengajarkan kita membangun tabel: baris, kolom, caption, sampai sel gabungan. Kini kita kembali ke struktur itu dengan sudut pandang baru, yaitu bagaimana screen reader membacanya sel demi sel. Tabel adalah konteks yang paling menyita perhatian: pengguna tak melihat garis kolom, melainkan mendengar satu sel pada satu waktu, sehingga hubungan sel dengan judul baris dan kolomnya harus eksplisit di kode.

Cara Screen Reader Membaca Tabel #

Ketika fokus masuk ke tabel, screen reader memperkenalkannya lewat caption, lalu pengguna berpindah sel dengan tombol panah. Pada setiap sel, pembaca layar menyebut dulu judul kolom dan judul baris terkait sebelum isi selnya — misalnya “kolom Stok, baris Bayam, 40 sachet”. Pada NVDA, navigasi ini memakai Ctrl+Alt beserta tombol panah. Mekanisme inilah sebabnya setiap judul harus benar-benar ditandai th, bukan sekadar teks tebal di dalam td, karena penanda itulah yang disambungkan browser ke sel-selnya.

caption dan scope untuk Tabel Sederhana #

Dua atribut yang pernah kita singgung pada chapter Caption dan Scope kini kita baca dari sisi pengumumannya. caption wajib menjadi anak pertama table dan diperkenalkan sebelum data, sedangkan scope pada th menyatakan judul itu berlaku untuk kolom (col) atau baris (row) berikutnya. Perhatikan contoh lengkapnya:

<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Stok Bibit</title>
</head>
<body>
  <h1>Stok Bibit Toko Bunga Melati</h1>
  <table>
    <caption>Stok bibit per akhir pekan ini</caption>
    <thead>
      <tr>
        <th scope="col">Bibit</th>
        <th scope="col">Stok</th>
        <th scope="col">Harga</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Bayam</th>
        <td>40 sachet</td>
        <td>Rp8.000</td>
      </tr>
      <tr>
        <th scope="row">Kangkung</th>
        <td>25 sachet</td>
        <td>Rp7.000</td>
      </tr>
    </tbody>
  </table>
</body>
</html>

Output yang Dihasilkan:

text
Menyusuri sel dengan panah, screen reader mengumumkan:
  - "Stok bibit per akhir pekan ini, tabel, 3 kolom, 3 baris"
  - "kolom Bibit, Bayam, baris 2"        (th scope="row" ikut dibacakan)
  - "kolom Stok, baris Bayam, 40 sachet"
  - "kolom Harga, baris Bayam, Rp8.000"

Perhatikan dua detail kecil yang berdampak besar: th scope="row" pada nama bibit membuat “Bayam” diperlakukan sebagai judul baris, sehingga setiap sel harga dan stok tetap terhubung dengan namanya. Sel td lain tidak butuh atribut tambahan pada tabel sederhana ini.

Kapan scope Tidak Cukup #

scope bekerja sempurna selama satu sel judul mewakili satu baris atau satu kolom utuh. Persoalan muncul pada tabel dua tingkat: satu judul kolom besar “Senin sampai Jumat” terbagi lagi menjadi “Buka” dan “Tutup”. Sel data di bawahnya kini punya dua judul kolom sekaligus, dan scope saja tak mampu menyatakan kombinasi tersebut. Kita perlu mekanisme penunjukan manual: atribut headers yang memuat daftar id semua judul yang berlaku untuk sel itu.

headers dan id untuk Tabel Dua Tingkat #

Contoh berikut memakai header dua tingkat, dan setiap sel data memanggil judulnya lewat headers:

<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Jam Operasional Toko</title>
</head>
<body>
  <h1>Jam Operasional Toko Bunga Melati</h1>
  <table>
    <caption>Jam buka per cabang, pekan 12 Februari 2024</caption>
    <thead>
      <tr>
        <th rowspan="2" id="hd-cabang" scope="col">Cabang</th>
        <th colspan="2" id="hd-kerja" scope="colgroup">Senin sampai Jumat</th>
        <th colspan="2" id="hd-akhir" scope="colgroup">Sabtu dan Minggu</th>
      </tr>
      <tr>
        <th id="hd-buka-kerja" scope="col">Buka</th>
        <th id="hd-tutup-kerja" scope="col">Tutup</th>
        <th id="hd-buka-akhir" scope="col">Buka</th>
        <th id="hd-tutup-akhir" scope="col">Tutup</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th id="hd-kemang" scope="row">Kemang</th>
        <td headers="hd-cabang hd-kerja hd-buka-kerja">08.00</td>
        <td headers="hd-cabang hd-kerja hd-tutup-kerja">20.00</td>
        <td headers="hd-cabang hd-akhir hd-buka-akhir">09.00</td>
        <td headers="hd-cabang hd-akhir hd-tutup-akhir">17.00</td>
      </tr>
      <tr>
        <th id="hd-serpong" scope="row">Serpong</th>
        <td headers="hd-cabang hd-kerja hd-buka-kerja">09.00</td>
        <td headers="hd-cabang hd-kerja hd-tutup-kerja">18.00</td>
        <td headers="hd-cabang hd-akhir hd-buka-akhir">09.00</td>
        <td headers="hd-cabang hd-akhir hd-tutup-akhir">15.00</td>
      </tr>
    </tbody>
  </table>
</body>
</html>

Output yang Dihasilkan:

text
Sel "08.00" cabang Kemang diumumkan sebagai:
  "kolom Buka, kolom Senin sampai Jumat, baris Kemang, 08.00"
Tiga judul itu bersumber dari nilai headers sel yang sama.

Mari kita bedah mekanisme penunjukannya:

  1. Baris 14-16 (th tingkat pertama): judul kolom besar diberi id unik (hd-kerja, hd-akhir) dan scope="colgroup" karena mencakup dua kolom di bawahnya; kolom Cabang membawa rowspan="2" agar menjulur melintasi dua baris header.
  2. Baris 19-22 (th tingkat kedua): empat judul “Buka” dan “Tutup” masing-masing punya id; tanpa id, atribut headers tak punya nama untuk dirujuk.
  3. Baris 27 (th scope="row" dengan id="hd-kemang"): judul baris cabang turut memiliki id agar bisa ikut disebut setiap sel data.
  4. Baris 28-31 (td dengan headers): tiap sel memanggil tiga judul sekaligus — cabang, kelompok hari, dan buka atau tutup — dalam urutan yang sama di seluruh tabel agar terdengar konsisten.

Atribut headers inilah jalan keluar resmi untuk tabel yang sel gabungannya tak terhindarkan. Struktur colspan dan rowspan yang menghasilkannya telah kita pelajari pada chapter Menggabungkan Sel; kini kita melihat harganya bagi pembaca layar.

Kurangi Sel Gabungan Bila Bisa #

Sebelum memakai headers, pertimbangkan menata ulang tabelnya, karena sel gabungan adalah sumber kesalahan paling umum pada tabel kompleks:

  • pecah satu tabel besar menjadi dua tabel kecil, misalnya tabel hari kerja dan tabel akhir pekan terpisah;
  • ulangi nilainya di setiap baris alih-alih menimpa dengan rowspan;
  • cukupkan satu tingkat header bila data bisa dirapikan ulang.

Bila struktur dua tingkat memang paling jujur menyatakan datanya, pasangkan id dengan headers seperti contoh di atas dan uji hasilnya dengan screen reader. Tabel yang bersih dari penggabungan tak perlu pola manual itu sama sekali. Setelah tabel, form, dan gambar beres, masih ada elemen yang kebutuhannya melampaui HTML native; jawabannya adalah ARIA pada chapter berikutnya.

Referensi resmi untuk pendalaman:

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

contoh-tabel-kompleks.html

Unduh berkas
html
<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Jam Operasional Toko</title>
</head>
<body>
  <h1>Jam Operasional Toko Bunga Melati</h1>
  <table>
    <caption>Jam buka per cabang, pekan 12 Februari 2024</caption>
    <thead>
      <tr>
        <th rowspan="2" id="hd-cabang" scope="col">Cabang</th>
        <th colspan="2" id="hd-kerja" scope="colgroup">Senin sampai Jumat</th>
        <th colspan="2" id="hd-akhir" scope="colgroup">Sabtu dan Minggu</th>
      </tr>
      <tr>
        <th id="hd-buka-kerja" scope="col">Buka</th>
        <th id="hd-tutup-kerja" scope="col">Tutup</th>
        <th id="hd-buka-akhir" scope="col">Buka</th>
        <th id="hd-tutup-akhir" scope="col">Tutup</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th id="hd-kemang" scope="row">Kemang</th>
        <td headers="hd-cabang hd-kerja hd-buka-kerja">08.00</td>
        <td headers="hd-cabang hd-kerja hd-tutup-kerja">20.00</td>
        <td headers="hd-cabang hd-akhir hd-buka-akhir">09.00</td>
        <td headers="hd-cabang hd-akhir hd-tutup-akhir">17.00</td>
      </tr>
      <tr>
        <th id="hd-serpong" scope="row">Serpong</th>
        <td headers="hd-cabang hd-kerja hd-buka-kerja">09.00</td>
        <td headers="hd-cabang hd-kerja hd-tutup-kerja">18.00</td>
        <td headers="hd-cabang hd-akhir hd-buka-akhir">09.00</td>
        <td headers="hd-cabang hd-akhir hd-tutup-akhir">15.00</td>
      </tr>
    </tbody>
  </table>
</body>
</html>

contoh-tabel-sederhana.html

Unduh berkas
html
<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Stok Bibit</title>
</head>
<body>
  <h1>Stok Bibit Toko Bunga Melati</h1>
  <table>
    <caption>Stok bibit per akhir pekan ini</caption>
    <thead>
      <tr>
        <th scope="col">Bibit</th>
        <th scope="col">Stok</th>
        <th scope="col">Harga</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">Bayam</th>
        <td>40 sachet</td>
        <td>Rp8.000</td>
      </tr>
      <tr>
        <th scope="row">Kangkung</th>
        <td>25 sachet</td>
        <td>Rp7.000</td>
      </tr>
    </tbody>
  </table>
</body>
</html>