Die Regel aria-required-children meldet ein Element, dessen ARIA-Rolle eine Struktur verspricht, die es nicht enthält: eine tablist ohne tab, eine listbox ohne option, ein menu ohne menuitem. Hilfstechnik sagt den Container an und findet darin nichts Brauchbares. Die Lösung: den Kindern die Rollen geben, die der Container verlangt – oder die Rolle am Container weglassen.
Was die Regel bedeutet
Manche ARIA-Rollen sind Container, die nur mit bestimmten Kindern Sinn ergeben; WAI-ARIA nennt sie „required owned elements“. Einige häufige Paare:
tablist→tablistbox→option(wahlweise in einergroup)menu/menubar→menuitem,menuitemcheckbox,menuitemradiolist→listitemgrid/table→row(in einerrowgroupoder direkt)
Die Regel schlägt an, wenn ein Container mit einer dieser Rollen kein Kind mit einer geforderten Rolle hat oder Kinder mit anderen Rollen dazwischenstehen. Kinder können echte Nachfahren sein oder über aria-owns zugeordnet werden.
Wen es betrifft
Screenreader-Nutzende. Eine tablist sagt „Registerkartenliste“ und die Zahl der Tabs an; eine listbox sagt Optionen an und lässt sich mit den Pfeiltasten durchgehen. Tragen die Kinder die Rollen nicht, ist die Zahl null, die Pfeiltasten haben kein Ziel, und das Widget zerfällt in unbeschriftete Buttons oder bloßen Text – oft ohne Hinweis, was ausgewählt ist.
Warum die Prüfung anschlägt
- Tabs aus Buttons in
role="tablist", ohnerole="tab"an jedem Button. - Eigene Auswahllisten mit
role="listbox", deren Einträge schlichte<div>s oder<li>s sind. - Hüllen dazwischen: ein
<div class="tab-wrapper">zwischen tablist und Tabs, ohnerole="presentation". - Leere Container, die vor den Einträgen gerendert werden, etwa Suchvorschläge – markieren Sie sie mit
aria-busy="true", bis sie gefüllt sind. - Kopiertes Markup, in dem die Container-Rolle überlebt hat und die Rollen der Einträge nicht.
So beheben Sie es
Geben Sie jedem Kind die Rolle, die der Container erwartet, mit den zugehörigen Zuständen.
<!-- Vorher: eine tablist mit einfachen Buttons -->
<div role="tablist" aria-label="Produktdetails">
<button type="button" class="tab is-active">Beschreibung</button>
<button type="button" class="tab">Bewertungen</button>
</div>
<!-- Nachher: echte Tabs mit Auswahlzustand und ihren Panels -->
<div role="tablist" aria-label="Produktdetails">
<button type="button" role="tab" id="tab-beschr" aria-selected="true" aria-controls="panel-beschr">Beschreibung</button>
<button type="button" role="tab" id="tab-bew" aria-selected="false" aria-controls="panel-bew" tabindex="-1">Bewertungen</button>
</div>
<div role="tabpanel" id="panel-beschr" aria-labelledby="tab-beschr">…</div>
<div role="tabpanel" id="panel-bew" aria-labelledby="tab-bew" hidden>…</div>
Die Rollen sind nur die halbe Arbeit: Eine tablist braucht auch Pfeiltasten, die zwischen den Tabs wechseln. Der ARIA Authoring Practices Guide beschreibt das Tastaturverhalten jedes Musters. Wollen Sie das nicht bauen, lassen Sie die ARIA-Rollen weg und nehmen einfache Buttons und Überschriften – besser als ein halbfertiges Widget.
So prüfen Sie es von Hand
- Öffnen Sie in den Entwicklertools den Barrierefreiheitsbaum und wählen Sie den Container. Stehen die Kinder mit den erwarteten Rollen darunter?
- Gehen Sie mit einem Screenreader auf das Widget. Sagt er die Zahl der Tabs, Optionen oder Einträge an?
- Nutzen Sie die Pfeiltasten im Widget. Wandert der Fokus so zwischen den Einträgen, wie das Muster es beschreibt?
- Prüfen Sie jeden Zustand – leer, ladend, gefiltert –, nicht nur den gefüllten.
Zugehöriges WCAG-Kriterium
1.3.1 Info und Beziehungen, Stufe A. Verwandt: 4.1.2 Name, Rolle, Wert, weil jeder Eintrag auch eine eigene Rolle und einen Zustand braucht.
So meldet Reviseberg diese Regel
Reviseberg führt aria-required-children auf jeder gecrawlten Seite aus. In der Befundliste steht die Regel mit Schweregrad, WCAG 1.3.1, der Zahl der betroffenen Elemente und Seiten und den Punkten, die ein Fix zurückbringt; im Detail sehen Sie Selektor und HTML-Ausschnitt des Containers. Komponenten werden meist geteilt, deshalb behebt ein Fix in der Komponentenbibliothek die Regel oft auf allen Seiten. Kann axe nicht entscheiden – bei manchen ganz leeren Containern wie einer listbox –, landet der Fall in der Warteschlange „Mögliche Probleme“ für einen Menschen. Ein Container, der beim Laden seiner Einträge aria-busy="true" trägt, wird nicht als Fehler gemeldet.