Proper Access Academy

Tabellen

Tabellen structureren data in rijen en kolommen. Gebruik ze alleen voor data, nooit voor layout.

Wanneer is een tabel een tabel?

Een tabel is bedoeld voor data die in rijen en kolommen thuishoort. Bijvoorbeeld een prijslijst, een rooster, vergelijkende specificaties of zoekresultaten. De relatie tussen rij en kolom is de informatie: “dit product kost dit bedrag” of “deze medewerker werkt op die dag”.

Gebruik een tabel niet voor layout. In de jaren negentig werden tabellen gebruikt om kolommen en witruimte te creeren. Dat patroon is achterhaald, maar komt nog steeds voor – vooral in e-mail templates en oudere websites. Een layout-tabel geeft een schermlezer verkeerde informatie: die leest “tabel met 3 rijen en 2 kolommen” terwijl er geen data-relatie is.

Hoe een schermlezer een tabel leest

Wanneer een schermlezer een goed gestructureerde tabel tegenkomt, gebeurt het volgende:

  1. De schermlezer kondigt de tabel aan: “tabel met 4 rijen en 3 kolommen”
  2. Als er een <caption> is, wordt de titel voorgelezen
  3. Bij navigatie door cellen leest de schermlezer de bijbehorende kolomkop mee: “Kolom: Prijs. 2.695 euro”

Dat werkt alleen als de tabel correct is opgebouwd met <th>, <td>, en scope.

De basisstructuur

Een toegankelijke tabel heeft deze onderdelen:

<table>
  <caption>Auditpakketten en prijzen</caption>
  <thead>
    <tr>
      <th scope="col">Pakket</th>
      <th scope="col">Prijs</th>
      <th scope="col">Doorlooptijd</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Quickscan</th>
      <td>&euro; 19</td>
      <td>1 werkdag</td>
    </tr>
    <tr>
      <th scope="row">Standaard audit</th>
      <td>&euro; 2.695</td>
      <td>3 weken</td>
    </tr>
  </tbody>
</table>
OnderdeelDoel
<caption>Titel van de tabel – beschrijft waar de tabel over gaat
<thead>Groepeert de koprij(en)
<tbody>Groepeert de datarijen
<th scope="col">Kolomkop – geldt voor alle cellen in die kolom
<th scope="row">Rijkop – geldt voor alle cellen in die rij
<td>Datacel

scope: de sleutel tot toegankelijke tabellen

Het scope-attribuut vertelt de schermlezer welke cellen bij welke kop horen. Zonder scope moet de schermlezer raden – en dat gaat bij complexere tabellen mis.

Voorbeeld: tabelkoppen

Fout

<table>
  <tr>
    <td><strong>Naam</strong></td>
    <td><strong>Functie</strong></td>
  </tr>
  <tr>
    <td>Fatima</td>
    <td>Developer</td>
  </tr>
</table>

De koppen zijn visueel vetgedrukt met <strong>, maar niet gemarkeerd als <th>. Een schermlezer leest “Fatima” zonder te melden dat het in de kolom “Naam” staat.

Goed

<table>
  <caption>Teamleden</caption>
  <thead>
    <tr>
      <th scope="col">Naam</th>
      <th scope="col">Functie</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Fatima</td>
      <td>Developer</td>
    </tr>
  </tbody>
</table>

Een schermlezer zegt bij “Developer”: “Kolom: Functie. Developer.” De relatie is duidelijk.

Caption: de titel van je tabel

Het <caption>-element beschrijft waar de tabel over gaat. Het wordt voorgelezen zodra de schermlezer de tabel aankondigt. Zo weet de gebruiker meteen of de tabel relevant is, voordat die door alle cellen navigeert.

Voorbeeld: caption

Niet ideaal

<h2>Openingstijden</h2>
<table>
  <thead>
    ...
  </thead>
</table>

De kop staat buiten de tabel. Een schermlezer die direct naar de tabel navigeert (via de tabellenlijst), mist de context.

Goed

<table>
  <caption>Openingstijden</caption>
  <thead>
    ...
  </thead>
</table>

De caption is onderdeel van de tabel en wordt altijd voorgelezen wanneer de tabel focus krijgt.

Caption vs. heading

Een <caption> is geen vervanging voor een kop in de pagina. Als je tabel een eigen sectie op de pagina inleidt, kun je zowel een kop (<h2>, <h3>) als een <caption> gebruiken. De kop is voor de paginastructuur, de caption is voor de tabelcontext.

Complexe tabellen

Soms heeft een tabel koppen op meerdere niveaus, samengevoegde cellen of kruisende koppen. In dat geval is scope niet genoeg en gebruik je het headers-attribuut:

<table>
  <caption>Beschikbaarheid per locatie</caption>
  <thead>
    <tr>
      <td></td>
      <th id="amsterdam" scope="col">Amsterdam</th>
      <th id="rotterdam" scope="col">Rotterdam</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th id="maandag" scope="row">Maandag</th>
      <td headers="amsterdam maandag">09:00 - 17:00</td>
      <td headers="rotterdam maandag">10:00 - 16:00</td>
    </tr>
  </tbody>
</table>

Elke <td> verwijst met headers naar de id’s van de bijbehorende koppen. Zo weet de schermlezer exact welke koppen bij welke cel horen – ook bij complexe structuren.

Vermijd complexe tabellen

Hoe complexer de tabel, hoe moeilijker het wordt voor alle gebruikers. Overweeg of je een complexe tabel kunt opsplitsen in meerdere eenvoudige tabellen. Dat is bijna altijd beter leesbaar en toegankelijker.

Layout-tabellen

Als je onverhoopt een tabel voor layout moet gebruiken (bijvoorbeeld in een HTML-e-mail), voeg dan role="presentation" toe. Dat vertelt de schermlezer dat het geen datatable is:

<table role="presentation">
  <tr>
    <td>Linkerkolom</td>
    <td>Rechterkolom</td>
  </tr>
</table>

De schermlezer negeert de tabelstructuur en leest alleen de inhoud. Gebruik geen <th>, <caption> of scope in een layout-tabel – dat zou tegenstrijdig zijn.

Tabel, lijst of beschrijvingslijst?

Niet alle gestructureerde data hoort in een tabel. De keuze hangt af van de relatie:

StructuurWanneer gebruiken
TabelData met rij-kolom-relaties (meerdere attributen per item)
Lijst (<ul>, <ol>)Opsomming van gerelateerde items zonder extra kolommen
Beschrijvingslijst (<dl>)Sleutel-waarde-paren (term + definitie)

Een adres met straat, postcode en woonplaats is geen tabel maar een adresblok. Een lijst van drie voordelen is geen tabel maar een <ul>. Een woordenlijst met termen en definities is een <dl>.

Voorbeeld: specificaties

Overbodig

<table>
  <tr>
    <th>Levertijd</th>
    <td>3 werkdagen</td>
  </tr>
  <tr>
    <th>Verzendkosten</th>
    <td>Gratis</td>
  </tr>
</table>

Dit zijn sleutel-waarde-paren, geen echte tabeldata. Er is maar een kolom met waarden.

Beter

<dl>
  <dt>Levertijd</dt>
  <dd>3 werkdagen</dd>

  <dt>Verzendkosten</dt>
  <dd>Gratis</dd>
</dl>

Een beschrijvingslijst past beter bij sleutel-waarde-paren.

WCAG-succescriteria

SuccescriteriumNiveauToelichting
1.3.1 Informatie en relatiesATabelkoppen moeten correct gekoppeld zijn aan datacellen
1.3.2 Betekenisvolle volgordeADe leesvolgorde van tabelcellen moet logisch zijn

Verder lezen

  • Tabellen – veelgemaakte fouten bij het opbouwen van tabellen

Quiz

Vraag 1. Een tabel heeft kolomkoppen die visueel vetgedrukt zijn met <td><strong>Naam</strong></td>. Wat is het probleem?
Vraag 2. Wat doet het scope-attribuut op een <th>?
Vraag 3. Een website gebruikt een <table> om twee kolommen naast elkaar te plaatsen: een afbeelding links en tekst rechts. Wat is het advies?
Vraag 4. Wat is het verschil tussen een <caption> en een <h2> boven een tabel?
Vraag 5. Een webshop toont productspecificaties als "Gewicht: 250g", "Kleur: zwart", "Materiaal: katoen". Wat is de beste HTML-structuur?