Sectie 1 · Hoofdstuk 7
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:
- De schermlezer kondigt de tabel aan: “tabel met 4 rijen en 3 kolommen”
- Als er een
<caption>is, wordt de titel voorgelezen - 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>€ 19</td>
<td>1 werkdag</td>
</tr>
<tr>
<th scope="row">Standaard audit</th>
<td>€ 2.695</td>
<td>3 weken</td>
</tr>
</tbody>
</table>
| Onderdeel | Doel |
|---|---|
<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.
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.
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:
| Structuur | Wanneer gebruiken |
|---|---|
| Tabel | Data 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>.
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
| Succescriterium | Niveau | Toelichting |
|---|---|---|
| 1.3.1 Informatie en relaties | A | Tabelkoppen moeten correct gekoppeld zijn aan datacellen |
| 1.3.2 Betekenisvolle volgorde | A | De leesvolgorde van tabelcellen moet logisch zijn |
Verder lezen
- Tabellen – veelgemaakte fouten bij het opbouwen van tabellen