4. November 2026
Barrierefreie Datentabellen HTML: th, scope, headers und caption mit Codebeispielen
Barrierefreie Datentabellen in HTML beruhen auf einem einfachen Prinzip: Jede Kopfzelle wird mit <th> ausgezeichnet, jede Datenzelle mit <td>, und das Markup legt die Beziehung zwischen beiden fest; bei komplexeren Tabellen können ausdrückliche Zuordnungen nötig sein. Genau das betont das Tabellen-Tutorial des W3C (WAI): Assistive Technologien stützen sich auf dieses Markup, um Nutzerinnen und Nutzern Kontext zu geben. Je nach Komplexität der Tabelle ergänzen Sie das Attribut scope oder die Attribute id und headers sowie in den meisten Fällen ein <caption>-Element, das der Tabelle einen Titel gibt. Dieser Leitfaden zeigt jeden Fall mit anpassbarem Code: Tabelle mit nur einer Kopfzeile oder -spalte, Tabelle mit Zeilen- und Spaltenköpfen, verbundene Kopfzellen, komplexe mehrstufige Tabelle, Beschriftung und Zusammenfassung sowie die Fehler, die Sie vermeiden sollten.
Warum Markup für barrierefreie Datentabellen in HTML unverzichtbar ist
Eine Tabelle ohne strukturelles Markup, die Kopfzellen nicht von Datenzellen unterscheidet und sie nicht korrekt verknüpft, schafft Barrieren. Sich allein auf visuelle Hinweise zu verlassen, reicht nicht: Kopf- und Datenzellen müssen von Software programmatisch ermittelt werden können.
In der Praxis liest ein Screenreader eine Zelle nach der anderen vor und nennt dabei die zugehörigen Zeilen- und Spaltenköpfe, sodass beim Navigieren durch die Tabelle der Kontext erhalten bleibt. Andere Menschen stellen die Daten anders dar, etwa mit eigenen Stylesheets, die Kopfzellen hervorheben, Textgröße und Farben ändern oder die Informationen als Listen statt als Raster anzeigen. Solche alternativen Darstellungen funktionieren nur, wenn der Tabellencode sauber strukturiert ist.
Mit Blick auf die WCAG ordnet das W3C-Tutorial diese Praktiken dem Erfolgskriterium 1.3.1 Info und Beziehungen (Stufe A) zu sowie den Techniken H51 (Tabellen-Markup zur Darstellung tabellarischer Informationen verwenden), H63 (das Attribut scope verwenden, um in Datentabellen Kopfzellen mit Datenzellen zu verknüpfen) und H39 (caption-Elemente verwenden, um Datentabellen eine Beschriftung zuzuordnen).
- Kopfzellen: <th>.
- Datenzellen: <td>.
- Komplexere Tabellen: Ausdrückliche Zuordnungen mit scope, id und headers können nötig sein.
- Diese Regeln gelten für Datentabellen, nicht für Layouttabellen.
Einfache Tabelle: <th> für Kopfzellen, scope gegen Mehrdeutigkeit
Der einfachste Fall ist eine Tabelle mit nur einem Kopf, entweder in der ersten Zeile oder in der ersten Spalte, deren Daten sich von Spalte zu Spalte klar unterscheiden. Bei einer kleinen Konzerttabelle (Datum, Veranstaltung, Ort) ist es nur deshalb akzeptabel, die erste Zeile mit <th> und den Rest mit <td> auszuzeichnen, weil die Tabelle so klein ist und sich die Daten in jeder Spalte deutlich unterscheiden, sodass die Beziehung zwischen Kopf- und Datenzellen offensichtlich ist. Das W3C weist jedoch darauf hin, dass manche Screenreader in der Zelle „Venue“ „Date – Event – Venue“ vorlesen, weil die Richtung der <th>-Elemente mehrdeutig ist.
Sobald die Daten nicht mehr für sich sprechen, ergänzen Sie das Attribut scope. Im W3C-Beispiel, einer Liste von Sammlern mit Nachname, Vorname und Stadt, lässt sich ohne Wissen um den zugehörigen Kopf nicht unterscheiden, was Nachname, Vorname oder Stadt ist. Der Wert col von scope legt die Richtung der Kopfzellen fest und verknüpft sie mit den Datenzellen ihrer Spalte. Laut W3C ist scope auch bei größeren Tabellen mit nur einer Kopfzeile oder -spalte nötig.
<table>
<caption>Teddybär-Sammler</caption>
<tr>
<th scope="col">Nachname</th>
<th scope="col">Vorname</th>
<th scope="col">Stadt</th>
</tr>
<tr>
<td>Phoenix</td>
<td>Imari</td>
<td>Henry</td>
</tr>
[…]
</table>Zeilen- und Spaltenköpfe: scope="col" und scope="row"
Hat eine Tabelle sowohl Spalten- als auch Zeilenköpfe, wird die Beziehung zwischen Kopf- und Datenzellen schnell mehrdeutig. Verwenden Sie <th> für alle Kopfzellen und legen Sie für jede die Richtung fest: scope="col" bedeutet, dass der Kopf für die ganze Spalte gilt, scope="row" für die ganze Zeile.
Das W3C-Beispiel ist eine Tabelle mit Lieferzeitfenstern: oben die Wochentage, links die Zeitspannen und in den Zellen „Offen“ oder „Geschlossen“. Diese Angaben sind nur nützlich, wenn sie einem bestimmten Tag und einer bestimmten Uhrzeit zugeordnet werden können. Die leere Zelle oben links bleibt ein <td>.
Dieselbe Technik funktioniert, wenn die Zeilenköpfe nicht in der ersten Spalte stehen. In einer Urlaubstabelle, deren erste Spalte eine ID und deren zweite Spalte den Namen der Person enthält, wird der Name als <th scope="row"> ausgezeichnet und gilt so für die Zellen links und rechts davon.
<table>
<caption>Lieferzeitfenster</caption>
<tr>
<td></td>
<th scope="col">Montag</th>
<th scope="col">Dienstag</th>
</tr>
<tr>
<th scope="row">09:00 – 11:00</th>
<td>Geschlossen</td>
<td>Offen</td>
</tr>
[…]
</table>Verbundene Kopfzellen: colgroup, rowgroup, thead und tbody
Erstreckt sich eine Kopfzelle über mehrere Spalten (colspan) oder Zeilen (rowspan), sollte sie mit den entsprechenden Zellen der Gruppe verknüpft werden, und zwar über scope="colgroup" oder scope="rowgroup". Zuvor muss jedoch die Struktur dieser Gruppen im Markup definiert sein.
Bei Spalten wird jede Spalte, von links beginnend, durch ein <col>-Element gekennzeichnet; überspannt ein Kopf mehrere Spalten, ersetzt ein <colgroup> mit span-Attribut diese Anzahl von <col>-Elementen. Die Summe der <col>-Elemente außerhalb von <colgroup> und der per span angegebenen Spalten der <colgroup>-Elemente sollte der Gesamtzahl der Tabellenspalten entsprechen. Bei Zeilen wird eine Gruppe durch <thead>, <tbody> oder <tfoot> definiert.
- <thead> und <tfoot> dürfen je einmal pro Tabelle verwendet werden.
- Eine Tabelle kann beliebig viele <tbody>-Elemente enthalten, die jeweils eine Zeilengruppe bilden.
- Überspannt ein Kopf mehrere Kopfzeilen, werden diese Zeilen statt in <tbody> in <thead> gruppiert; überspannt er mehrere Zeilen im Fußbereich, verwenden Sie <tfoot>.
- Das W3C merkt an, dass die Verwendung von <thead>, <tbody> und <tfoot> in jeder Tabelle Unsicherheit darüber vermeiden kann, wann sie einzusetzen sind.
<table>
<col>
<colgroup span="2"></colgroup>
<colgroup span="2"></colgroup>
<tr>
<td rowspan="2"></td>
<th colspan="2" scope="colgroup">Mars</th>
<th colspan="2" scope="colgroup">Venus</th>
</tr>
<tr>
<th scope="col">Hergestellt</th>
<th scope="col">Verkauft</th>
<th scope="col">Hergestellt</th>
<th scope="col">Verkauft</th>
</tr>
<tr>
<th scope="row">Teddybären</th>
<td>50.000</td>
<td>30.000</td>
<td>100.000</td>
<td>80.000</td>
</tr>
[…]
</table>Komplexe Tabelle: jede Zelle mit headers und id verknüpfen
Manche Tabellen sind zu komplex, um Kopf- und Datenzellen streng horizontal oder vertikal zuzuordnen. Das W3C nennt zwei Fälle: Tabellen, deren Spaltenköpfe sich mitten in der Tabelle wiederholen oder ändern, und Tabellen, in denen jeder Datenzelle drei oder mehr Kopfzellen zugeordnet sind.
Die Methode: Jedes <th> erhält eine im gesamten Dokument eindeutige id, und jedes <td> listet in seinem headers-Attribut die id oder ids der zugehörigen Kopfzellen auf, getrennt durch Leerzeichen. Im W3C-Beispiel zur Verfügbarkeit von Ferienunterkünften ist die Zelle „11“ gleichzeitig mit der Stadt (Paris), der Zimmerzahl (1 Schlafzimmer) und der Unterkunftsart (Studio) verknüpft.
Ein Tipp aus dem Tutorial: In einer Tabelle mit Lieferantenkontakten, deren Köpfe sich auf halber Höhe ändern, verweisen die Kopfzellen selbst auf eine leere Zelle mit der id „blank“. Das verhindert, dass manche assistiven Technologien für diese Kopfzellen einen Kopf vorlesen.
Fragen Sie sich vorher, ob die Tabelle wirklich so komplex sein muss. Das W3C schlägt vor, sie in vielen Fällen in kleinere Tabellen aufzuteilen: Die Informationen werden für alle leichter verständlich und leichter zu programmieren, und einfache Tabellen werden von Werkzeugen zur Inhaltserstellung, einschließlich WYSIWYG-Editoren, deutlich besser unterstützt.
[…]
<tr>
<th id="par" colspan="5" scope="colgroup">Paris</th>
</tr>
<tr>
<th id="pbed1">1 Schlafzimmer</th>
<td headers="par pbed1 stud">11</td>
<td headers="par pbed1 apt">20</td>
[…]
</tr>Beschriftung mit <caption> und Zusammenfassung komplexer Tabellen
Die Beschriftung wirkt wie eine Überschrift der Tabelle. Die meisten Screenreader lesen sie vor; sie hilft, die Tabelle zu finden, ihr Thema zu verstehen und zu entscheiden, ob man sie lesen möchte. Wer im „Tabellenmodus“ von Tabelle zu Tabelle springt, identifiziert Tabellen in erster Linie über die Beschriftung. Sie wird mit dem Element <caption> umgesetzt, das direkt als Kind von <table> steht, und sollte eine kurze Überschrift sein, etwa „Konzerte“.
Die Zusammenfassung beschreibt, wie die Daten organisiert sind, und erleichtert die Navigation; sie ist meist nur bei komplexen Tabellen nötig. Wenn Sie beides angeben, sollte die Zusammenfassung keine Informationen wiederholen, die bereits in der Beschriftung stehen. Das W3C betont, dass Beschriftung und Zusammenfassung nicht in jedem Fall erforderlich sind, um die WCAG zu erfüllen, aber recht einfache Wege sind, häufig benötigte Informationen bereitzustellen.
- Zusammenfassung in <caption>: Der Text folgt auf den Titel, etwa in einem <span>, und ist auch für sehende Nutzer sichtbar.
- Zusammenfassung über aria-describedby an <table>, das auf ein beliebiges Element mit eindeutiger id verweist, zum Beispiel einen Absatz. Das Element muss nicht vor der Tabelle stehen; steht es aber nahe der Tabelle, finden Nutzer die Zusammenfassung schneller, besonders wenn sie keinen Screenreader verwenden. Das W3C warnt, dass diese WAI-ARIA-Funktion von assistiven Technologien möglicherweise weniger breit unterstützt wird.
- Tabelle in <figure> mit <figcaption>: Im „Tabellenmodus“ können Screenreader-Nutzer die Tabelle über eine so angebrachte Beschriftung meist nicht identifizieren. Der Beschriftungsteil von <figcaption> kann per aria-labelledby, der Zusammenfassungsteil per aria-describedby ausdrücklich mit der Tabelle verknüpft werden; das kann dazu führen, dass beide mehrfach vorgelesen werden. Das W3C warnt auch, dass diese HTML5-Funktion von assistiven Technologien möglicherweise weniger breit unterstützt wird.
<table>
<caption>Verfügbarkeit von Ferienunterkünften<br>
<span>Spalte eins enthält Ort und Größe der Unterkunft, die übrigen Spalten Art und Anzahl der verfügbaren Unterkünfte</span>
</caption>
[…]
</table>Was Sie in einer HTML-Datentabelle vermeiden sollten
Die Seite „Tips and Tricks“ des Tutorials nennt mehrere Praktiken, die Sie vermeiden sollten.
- <td>-Zellen so gestalten, dass sie wie Köpfe aussehen: Verwenden Sie <th>, sonst wird die Tabelle weniger zugänglich oder sogar unzugänglich. Hilfreich ist außerdem, <th> und <td> visuell zu unterscheiden.
- Mehrere Tabellen mit einer zusätzlichen <th>-Zeile zu einer zusammenfassen: Screenreader lesen unter Umständen alle <th>-Zellen einer Spalte vor. Beginnen Sie ein neues <table>, wenn das Thema wechselt.
- Köpfe in eine Spalte und alle Daten in eine zweite setzen: Jede Angabe braucht ihre eigene Zelle.
- Pseudozeilen mit <br> erzeugen: Die Daten dieser Pseudozeilen sind bei geänderter Textgröße womöglich nicht mehr korrekt ausgerichtet.
- Die Tabelle auf kleinen Bildschirmen oder beim Zoomen abschneiden, etwa mit overflow: hidden in CSS. Das Tutorial setzt overflow: scroll auf ein Element, das die Tabelle umschließt; es gibt aber viele weitere Darstellungsmöglichkeiten.
- Die Struktur im responsiven Layout verlieren: Die Beziehung zwischen Kopf- und Datenzellen muss in allen Formaten erhalten bleiben.
- Tabellen für das Layout nutzen: Verwenden Sie CSS. Gibt es bereits Layouttabellen, setzen Sie darin weder die strukturellen Elemente (wie <th> oder <caption>) noch die im Tutorial behandelten Attribute (scope, headers…) ein und ergänzen Sie role="presentation" am <table>-Element.
Häufige Fragen
Wie mache ich eine HTML-Tabelle barrierefrei?
Zeichnen Sie Kopfzellen mit <th> und Datenzellen mit <td> aus. Ergänzen Sie scope="col" oder scope="row", wenn die Richtung der Köpfe mehrdeutig ist, scope="colgroup" oder scope="rowgroup" für verbundene Kopfzellen sowie id und headers, wenn die Zuordnung nicht streng horizontal oder vertikal möglich ist (Köpfe, die sich mitten in der Tabelle ändern, drei oder mehr Köpfe pro Zelle). In den meisten Situationen geben Sie der Tabelle außerdem mit <caption> einen Titel: Die WCAG verlangen das nicht in jedem Fall, aber es ist nützlich.
Was ist der Unterschied zwischen scope und headers?
scope gibt die Richtung eines Kopfes an: col, row, colgroup oder rowgroup. Das genügt, solange die Zuordnung streng horizontal oder vertikal ist. headers, meist an einer Datenzelle, listet ausdrücklich die ids der zugehörigen Kopfzellen auf; es wird gebraucht, wenn sich Köpfe mitten in der Tabelle ändern oder jeder Zelle drei oder mehr Köpfe zugeordnet sind.
Ist das caption-Element in einer Tabelle Pflicht?
Laut W3C sind Beschriftung und Zusammenfassung nicht in jedem Fall erforderlich, um die WCAG zu erfüllen. Eine Beschriftung ist dennoch in den meisten Situationen nützlich: Die meisten Screenreader lesen sie vor, und im Tabellenmodus ist sie das wichtigste Mittel, um eine Tabelle zu identifizieren.
Brauche ich scope bei einer einfachen Tabelle?
Nicht immer: <th> ohne scope ist nur bei einer kleinen Tabelle akzeptabel, deren Daten sich in jeder Spalte deutlich unterscheiden; selbst dann lesen manche Screenreader in der Zelle „Venue“ „Date – Event – Venue“ vor, weil die Richtung der <th>-Elemente mehrdeutig ist. Sobald die Daten mehrdeutig sind oder die Tabelle größer ist und nur eine Kopfzeile oder -spalte hat, ergänzen Sie scope.
Darf man HTML-Tabellen für das Layout verwenden?
Nein, das W3C empfiehlt CSS für das Layout. In einer bestehenden Layouttabelle verwenden Sie weder strukturelle Elemente wie <th> oder <caption> noch die in diesem Leitfaden behandelten Attribute (scope, headers…) und ergänzen role="presentation" am <table>-Element.
Weiterlesen bei Conformly
Quellen
Dieser Artikel stützt sich auf die am Seitenende genannten offiziellen Quellen.