Fehlerhafte Tabellen-Zuordnung (td-headers-attr)

Die Regel td-headers-attr meldet eine Tabellenzelle, deren headers-Attribut auf etwas verweist, das keine Kopfzelle derselben Tabelle ist – eine fehlende ID, ein Tippfehler oder eine Zelle in einer anderen Tabelle. Ein Screenreader liest den Wert dann ohne die Spalte und Zeile vor, zu der er gehört. Die Lösung: headers auf echte <th>-IDs derselben Tabelle zeigen lassen – oder bei einer einfachen Tabelle headers weglassen und scope nutzen.

Was die Regel bedeutet

In einer Datentabelle gehört jede Datenzelle zu einer oder mehreren Kopfzellen. Die meisten Tabellen drücken das allein über die Struktur aus: <th> in der ersten Zeile und ersten Spalte, am besten mit scope="col" oder scope="row". Komplexe Tabellen – Kopfzellen über mehrere Spalten, mehrere Kopfebenen – können die Beziehung ausdrücklich benennen: Jede <td> bekommt ein headers-Attribut mit den IDs ihrer Kopfzellen.

Die Regel prüft jedes headers-Attribut: Jede ID muss zu einer Zelle derselben Tabelle gehören, und eine Zelle darf sich nicht selbst nennen. Ob die genannten Kopfzellen die richtigen sind, prüft sie nicht.

Wen es betrifft

Blinde und sehbehinderte Menschen mit Screenreader. Wer eine Tabelle Zelle für Zelle durchgeht, hört zu jeder Zelle ihre Kopfzellen – „Express, Preis, 9,90 €“. Mit kaputtem headers-Attribut fehlt diese Ansage oder ist falsch, und aus einer Tabelle voller Zahlen wird eine Liste von Zahlen ohne Bedeutung.

Warum die Prüfung anschlägt

  • Geänderte IDs – eine Vorlage hat die IDs der Kopfzellen umbenannt, die Zellen haben die alten behalten.
  • Erzeugte IDs, die sich zwischen Kopfzeile und Tabellenkörper unterscheiden, etwa ein Zähler, der pro Abschnitt neu beginnt.
  • Zwei Tabellen auf einer Seite mit denselben IDs, sodass Zellen in die andere Tabelle zeigen.
  • Kopierte Zeilen aus einer anderen Tabelle im Redaktionssystem.
  • headers, wo scope genügt hätte – das vervielfacht die Stellen, an denen eine ID brechen kann.

So beheben Sie es

Lassen Sie jeden headers-Wert auf die ID einer <th> derselben Tabelle zeigen.

<!-- Vorher: Die Zellen verweisen auf IDs, die es nicht gibt -->
<table>
  <caption>Versandarten</caption>
  <tr><th id="art">Versandart</th><th id="preis">Preis</th></tr>
  <tr><td headers="versand">Standard</td><td headers="kosten">4,90 €</td></tr>
  <tr><td headers="versand">Express</td><td headers="kosten">9,90 €</td></tr>
</table>
<!-- Nachher: Eine einfache Tabelle braucht gar kein headers-Attribut -->
<table>
  <caption>Versandarten</caption>
  <tr><th scope="col">Versandart</th><th scope="col">Preis</th></tr>
  <tr><th scope="row">Standard</th><td>4,90 €</td></tr>
  <tr><th scope="row">Express</th><td>9,90 €</td></tr>
</table>

Behalten Sie headers für Tabellen, deren Struktur scope nicht ausdrücken kann – etwa ein Fahrplan mit zwei Kopfzeilen. Erzeugen Sie dann IDs und Verweise aus denselben Daten, damit sie nicht auseinanderlaufen.

So prüfen Sie es von Hand

  1. Suchen Sie in den Entwicklertools nach jeder ID, die ein headers-Attribut nennt. Gibt es sie, und ist sie eine <th> derselben Tabelle?
  2. Gehen Sie die Tabelle mit einem Screenreader Zelle für Zelle durch (in NVDA: Strg + Alt + Pfeiltasten). Werden zu jeder Zelle die richtigen Kopfzellen angesagt?
  3. Prüfen Sie Tabellen mit verbundenen Kopfzellen besonders gründlich – dort wird headers wirklich gebraucht.
  4. Fragen Sie, ob die Tabelle headers überhaupt braucht. Eine Tabelle mit einer Kopfzeile und einer Kopfspalte braucht es nicht.

Zugehöriges WCAG-Kriterium

1.3.1 Info und Beziehungen, Stufe A. Verwandt: 1.3.2 Bedeutungsvolle Reihenfolge, weil eine Tabelle auch der Reihe nach gelesen Sinn ergeben muss.

So meldet Reviseberg diese Regel

Reviseberg führt td-headers-attr auf jeder gecrawlten Seite aus. In der Befundliste steht die Regel mit Schweregrad, WCAG 1.3.1, der Zahl der betroffenen Zellen und Seiten und den Punkten, die ein Fix zurückbringt; im Detail sehen Sie Selektor und HTML-Ausschnitt jeder Zelle. Tabellen aus derselben Vorlage scheitern auf dieselbe Weise, deshalb zeigt die Seitenspalte meist auf die Vorlage, die zu reparieren ist. Ob die genannten Kopfzellen die richtigen sind, kann die Regel nicht beurteilen – das prüfen Sie mit einem Screenreader.

Verwandte Regeln

  • undefined – ein Listeneintrag außerhalb einer Liste.
  • undefined – Listenstruktur, die andere häufige 1.3.1-Struktur.
  • undefined – eine Überschrift ohne Text.

Tabellen auf Ihrer Website prüfen – kostenloser Scan

Häufige Fragen

Soll ich headers oder scope verwenden?

scope für einfache Tabellen mit einer Kopfzeile und einer Kopfspalte; headers nur für komplexe Tabellen, die scope nicht beschreiben kann.

Darf headers auf eine <td> zeigen?

Das Attribut darf auf jede Zelle derselben Tabelle verweisen, und axe akzeptiert das. In der Praxis sollten die genannten Zellen <th> sein, damit jedes Werkzeug sie als Kopfzellen behandelt.

Braucht eine Layout-Tabelle headers?

Nein. Eine Tabelle fürs Layout sollte gar keine Kopfzellen haben – besser noch: CSS statt Tabelle.

Quellen

  1. W3C, Understanding SC 1.3.1 Info and Relationships – https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships
  2. Deque University, axe-core 4.13 Regel td-headers-attr – https://dequeuniversity.com/rules/axe/4.13/td-headers-attr
  3. W3C WAI, Tables Tutorial: Tables with multi-level headers – https://www.w3.org/WAI/tutorials/tables/multi-level/
  4. W3C, Technique H43: Using id and headers attributes to associate data cells with header cells – https://www.w3.org/WAI/WCAG22/Techniques/html/H43

Sehen Sie, was ein Scan auf Ihrer Website findet

Eine Seite in rund 30 Sekunden, ohne E-Mail. Der vollständige Bericht umfasst bis zu 100 Seiten und einen Tastatur-Durchlauf.