Fehlende Tabellenüberschriften: Warum Datentabellen th brauchen, nicht nur fetten Text
Schauen Sie sich mit Ihren Augen eine beliebige Datentabelle an, und die Kopfzeile ist offensichtlich – sie ist meist fett, vielleicht anders schattiert, sitzt oben oder am linken Rand. Ein Screenreader-Nutzer, der Zelle für Zelle navigiert, bekommt diesen visuellen Kontext nicht kostenlos; ohne echtes Markup, das jede Datenzelle mit ihrer Überschrift verknüpft, bedeutet das Durchgehen einer 40-zeiligen Tabelle, eine Wand aus bloßen Zahlen und Wörtern zu hören, ohne zu wissen, was irgendetwas davon bedeutet.
Dies fällt unter WCAG-Erfolgskriterium 1.3.1 (Info und Beziehungen), Stufe A.
Die Lösung für einfache Tabellen
Verwenden Sie <th> für Kopfzellen statt eines gestylten <td>, und setzen Sie scope, um festzulegen, ob die Überschrift für ihre Spalte oder ihre Zeile gilt:
<!-- Vorher: Überschriften sind nur fetter Text, keine echten Kopfzellen -->
<table>
<tr><td><b>Name</b></td><td><b>Umsatz</b></td></tr>
<tr><td>Acme GmbH</td><td>1,2 Mio. €</td></tr>
</table>
<!-- Nachher: echte Kopfzellen, ausdrücklich zugeordnet -->
<table>
<thead>
<tr><th scope="col">Name</th><th scope="col">Umsatz</th></tr>
</thead>
<tbody>
<tr><td>Acme GmbH</td><td>1,2 Mio. €</td></tr>
</tbody>
</table>
Ein Screenreader kann nun "Umsatz: 1,2 Mio. €" ankündigen, wenn er auf dieser Zelle landet, statt nur "1,2 Mio. €" – die scope="col"-Zuordnung ist es, die den Spaltennamen automatisch liefert.
Komplexe Tabellen benötigen explizite id/headers-Zuordnung
Einfaches scope versagt bei Tabellen mit mehrstufigen oder unregelmäßigen Überschriften (eine Tabelle mit sowohl Zeilen- als auch Spaltenüberschriften, oder zusammengeführten Kopfzellen, die mehrere Spalten überspannen). Dafür erhält jedes <th> eine eindeutige id, und jede Datenzelle listet über das headers-Attribut genau auf, welche Kopf-IDs gelten:
<table>
<tr>
<th id="q1">Q1</th>
<th id="q2">Q2</th>
</tr>
<tr>
<th id="umsatz">Umsatz</th>
<td headers="umsatz q1">1,2 Mio. €</td>
<td headers="umsatz q2">1,4 Mio. €</td>
</tr>
</table>
Dies ist ausführlicher, aber der einzige zuverlässige Weg, die Bedeutung einer Datenzelle in einer tatsächlich mehrdimensionalen Tabelle eindeutig zu machen.
Das Erste, was zu prüfen ist: Ist dies überhaupt eine Datentabelle?
Tabellen, die rein für visuelles Layout verwendet werden (ein verbreitetes Muster bei älteren Websites und in manchem automatisch generiertem oder aus E-Mails exportiertem HTML), sollten überhaupt keine <th>-Elemente hinzugefügt bekommen – das würde Layout-Zellen fälschlicherweise als Datenüberschriften ankündigen. Wenn eine Tabelle keine logische Zeilen-und-Spalten-Beziehung zu vermitteln hat, ist die bessere Lösung meist, die Tabelle vollständig durch semantisches Nicht-Tabellen-Markup zu ersetzen (Divs und CSS Grid/Flexbox), statt Kopfzeilen-Markup auf etwas nachzurüsten, das nie wirklich tabellarische Daten waren.
Offizielle Referenzen
- Deque University: table-fake-caption
- Deque University: td-has-header
- W3C Technique H43
- W3C Technique H51
- W3C Technique H63
- W3C Technique H73
Häufige Fragen
- Warum genügt fetter Text nicht als Tabellenkopf?
- Fetter oder hinterlegter Text ist nur ein visueller Hinweis. Ein Screenreader, der Zelle für Zelle navigiert, braucht echtes `<th>`-Markup, um die zugehörige Überschrift anzusagen; reine Gestaltung vermittelt ihm nichts.
- Wie zeichne ich Tabellenköpfe korrekt aus?
- Verwenden Sie `<th>` für Kopfzellen und ergänzen Sie `scope=col` oder `scope=row`, damit jede Datenzelle der richtigen Überschrift zugeordnet ist. Bei komplexen Tabellen verknüpfen Sie Zellen über `headers` und `id`.
- Gilt das auch für Layout-Tabellen?
- Nein – es geht um Datentabellen. Rein zur Gestaltung genutzte Tabellen sollten durch CSS ersetzt werden und brauchen nie `<th>`; die Anforderung gilt für Tabellen mit echten tabellarischen Daten.
Verwandte Artikel
Möchten Sie sehen, wie Ihre eigene Website abschneidet?
Kostenlosen Barrierefreiheitsscan durchführen