Komponenten · Interaktive Widgets

Comboboxen & Autocomplete

Ein Vorschlagsfeld baust du barrierefrei, indem du zuerst prüfst, ob das native <datalist> reicht – es kommt ohne ARIA, ohne Tastaturlogik und ohne JavaScript aus. Erst wenn du filtern, gestalten oder gruppieren musst, kommt das ARIA-Combobox-Pattern: ein Textfeld mit role="combobox", gepflegtem aria-expanded und aria-activedescendant, das den Tastaturfokus im Eingabefeld belässt.

Ein Eingabefeld, das beim Tippen Vorschläge zeigt, gehört zu den nützlichsten und zugleich kniffligsten Komponenten. Knifflig, weil zwei Bedienmodelle zusammenkommen: Texteingabe und Listenauswahl. Der Screenreader muss beides gleichzeitig verfolgen – was du tippst und was in der Liste gerade hervorgehoben ist. Genau daran scheitern die meisten Eigenbauten.

Das Wichtigste in Kürze

  • <datalist> zuerst. Es ist die einzige Variante, die keinerlei ARIA braucht und bei der nichts auseinanderlaufen kann.
  • Aber <datalist> hat harte Grenzen: Die Liste lässt sich nicht gestalten, zoomt nicht mit, ignoriert den Kontrastmodus – und wird nicht von jeder Screenreader-Kombination angesagt.
  • Für reine Auswahl ohne Tippen ist <select> richtig – und seit appearance: base-select auch gestaltbar.
  • role="combobox" gehört ans Eingabefeld, nicht an einen Wrapper. Das hat sich mit ARIA 1.2 geändert.
  • aria-activedescendant ist kein zweiter Fokus. Der echte Fokus bleibt im Feld, alle Tastaturereignisse feuern dort.
  • aria-expanded muss immer stimmen – es ist die einzige Auskunft darüber, ob die Liste offen ist.
  • Die Trefferzahl gehört in eine Live-Region. Sonst ist die Liste für Sehende da und für alle anderen nicht.
  • autocomplete="off" nicht blind setzen: Bei Feldern mit Autofill-Zweck (Name, Adresse, E-Mail) kollidiert das mit 1.3.5.

Der einfache Weg: <datalist>

Für viele Fälle reicht das native <datalist>: ein Eingabefeld mit Vorschlagsliste, ganz ohne JavaScript und ARIA. Nebenbei ist die Vorschlagsliste einer Website-Suche eine der ehrlichsten Quellen dafür, wonach Menschen tatsächlich suchen – wie man daraus Themen ableitet, steht unter Suchintention verstehen.

<label for="stadt">Stadt</label>
<input list="staedte" id="stadt" name="stadt" />
<datalist id="staedte">
  <option value="Berlin"></option>
  <option value="Hamburg"></option>
  <option value="München"></option>
</datalist>

Was du dafür geschenkt bekommst, ist beachtlich: Filtern beim Tippen, Tastaturbedienung mit Pfeiltasten und Enter, Schließen mit Escape, korrekte Rollenzuweisung im Accessibility-Tree – und Verhalten, das zum Betriebssystem passt. Ein Eingabefeld mit list-Attribut ist laut Spezifikation bereits eine Combobox; du musst kein einziges ARIA-Attribut ergänzen. Wer es trotzdem tut, macht es schlechter.

Zwei Eingabefelder nebeneinander, jeweils mit offener Vorschlagsliste. Links das native datalist mit drei Vorschlägen und der Notiz: kein ARIA, keine Tastaturlogik, aber nicht gestaltbar und nicht zoomend. Rechts das ARIA-Combobox-Pattern mit hervorgehobenem zweitem Eintrag, eingezeichneten Attributen role=combobox, aria-expanded=true, aria-controls und aria-activedescendant, einer gestrichelten Linie vom Attribut zur hervorgehobenen Option und dem Hinweis, dass der Tastaturfokus im Eingabefeld bleibt.
Links macht der Browser die Arbeit, rechts du. Der Unterschied im Aufwand ist ungefähr so groß wie der im Bild.

Was <datalist> nicht kann

Die ehrliche Bilanz – denn diese Punkte entscheiden, ob du beim nativen Element bleiben kannst:

Grenze Auswirkung
Keine Gestaltung der Liste Schriftart, Farben, Gruppen, Icons: nicht möglich
Kein Mitzoomen Die Vorschläge bleiben klein, auch bei 400 % Seiten-Zoom
Kein Kontrastmodus Im erzwungenen Farbmodus bleibt die Liste, wie sie ist
Ansage nicht überall Manche Kombinationen (u. a. NVDA mit Firefox) lesen die Vorschläge nicht vor
value vs. Textinhalt Browser zeigen <option value="B">Berlin</option> unterschiedlich an

Vor allem der Zoom-Punkt wiegt schwer: Wer die Seite auf 400 % vergrößert, weil er sie sonst nicht lesen kann, bekommt eine Vorschlagsliste in Originalgröße. Das ist genau die Nutzergruppe, für die die Funktion gedacht war. Diese Lücken sind bekannt und stehen bei den Browserherstellern auf der gemeinsamen Interop-Liste – behoben sind sie noch nicht.

Trotzdem gilt: Solange die Vorschläge eine Hilfe sind und nicht der einzige Weg zur Eingabe – der Nutzer könnte also auch einfach tippen –, ist <datalist> die robusteste Lösung. Kritisch wird es erst, wenn die Auswahl verpflichtend ist.

Nur auswählen? Dann <select>

Ein Punkt, der in der Combobox-Diskussion oft untergeht: Wenn gar nicht getippt werden soll, ist eine Combobox das falsche Werkzeug. Für die Auswahl aus einer überschaubaren, festen Menge ist <select> unschlagbar – tastaturbedienbar, auf dem Handy mit Systemauswahl, ohne eine Zeile JavaScript.

Das klassische Gegenargument war die Gestaltung. Das ist inzwischen erledigt: Mit appearance: base-select lässt sich das native <select> samt aufgeklapptem Menü gestalten, und <selectedcontent> spiegelt die gewählte Option in den geschlossenen Knopf. Chrome und Edge unterstützen das seit 2025, Safari ist nachgezogen, Firefox arbeitet daran (Stand Juli 2026).

select, ::picker(select) { appearance: base-select; }

Das Schöne daran: Es ist reine Progressive Enhancement. Ein Browser, der die Regel nicht kennt, ignoriert sie und zeigt ein ganz normales, voll funktionsfähiges <select>. Mehr dazu unter Menüs & Dropdowns.

Der ARIA-Weg: das Combobox-Pattern

Brauchst du gefilterte Treffer, eigene Gestaltung, Gruppen oder Zusatzinfos pro Eintrag, baust du das Combobox-Pattern nach. Es verbindet ein Textfeld mit einer Listbox:

<label for="frucht">Frucht</label>
<input
  id="frucht"
  type="text"
  role="combobox"
  aria-expanded="false"
  aria-controls="frucht-liste"
  aria-autocomplete="list"
  autocomplete="off"
/>
<ul id="frucht-liste" role="listbox" aria-label="Vorschläge" hidden>
  <li id="opt-1" role="option">Apfel</li>
  <li id="opt-2" role="option">Aprikose</li>
</ul>

<p class="visually-hidden" role="status"></p>

Vier Dinge daran sind leicht falsch zu machen:

role="combobox" sitzt am <input>. In ARIA 1.1 lag die Rolle noch auf einem umschließenden <div>, und viele Tutorials und Komponentenbibliotheken hängen bis heute an dieser Fassung. Seit ARIA 1.2 ist das Eingabefeld selbst die Combobox – das ist die Form, die aktuelle Browser und Screenreader erwarten.

aria-controls zeigt auf die Liste, nicht aria-owns. Die Liste muss dabei nicht im DOM daneben liegen – aber sie muss existieren, auch wenn sie hidden ist.

aria-expanded ist Pflicht und muss stimmen. Es ist die einzige Information darüber, ob gerade Vorschläge da sind. Ein aria-expanded, das beim Schließen vergessen wird, ist schlimmer als keines: Der Screenreader meldet dann eine Liste, die es nicht mehr gibt.

Die hervorgehobene Option trägt aria-selected="true" – und zwar immer genau eine.

aria-activedescendant: der Kern des Musters

Das eigentliche Kunststück: Der Tastaturfokus bleibt im Eingabefeld, während die Pfeiltasten durch die Liste wandern. Möglich macht das aria-activedescendant, das per ID auf die gerade hervorgehobene Option zeigt:

function hervorheben(option) {
  liste.querySelectorAll('[role="option"]')
    .forEach(o => o.setAttribute('aria-selected', String(o === option)));
  eingabe.setAttribute('aria-activedescendant', option.id);
  option.scrollIntoView({ block: 'nearest' });
}

Sarah Higley bringt den entscheidenden Punkt auf den Nenner: aria-activedescendant ist kein zweiter Fokus. Es gibt kein document.activeDescendant, alle Tastaturereignisse feuern weiterhin am Eingabefeld, und der Browser scrollt die Option nicht von selbst ins Bild – deshalb das scrollIntoView oben. Aus ihrer Analyse folgen zwei harte Regeln:

  1. Zeige nur auf Elemente innerhalb der Liste, auf die aria-controls verweist. Ein aria-activedescendant, das auf ein beliebiges fokussierbares Element außerhalb zeigt, bringt Windows-Screenreader zwischen Lese- und Formularmodus durcheinander.
  2. Auch Zusatzeinträge brauchen role="option". Ein „Mehr laden“ oder „Kein Treffer“ am Listenende muss dieselbe Rolle tragen wie die echten Vorschläge, sonst kippt der Modus.

Die Alternative wäre Roving Tabindex – der Fokus wandert wirklich in die Liste. Für eine Combobox ist das die schlechtere Wahl: Sobald der Fokus das Textfeld verlässt, funktioniert Weitertippen nicht mehr. Für Bäume, Grids und virtualisierte Listen dagegen ist Roving Tabindex robuster.

Tastatur: was funktionieren muss

Taste Erwartetes Verhalten
Pfeil ↓ Liste öffnen bzw. zur nächsten Option
Pfeil ↑ Zur vorherigen Option; von der ersten aus zurück ins Feld
Enter Hervorgehobene Option übernehmen, Liste schließen
Esc Erst Liste schließen; zweites Esc leert das Feld
Tab Übernehmen (bei Inline-Vervollständigung) und weiterspringen
Alt + ↓ Liste öffnen, ohne eine Option zu wählen

Alles davon ist Erwartung, nicht Kür: Wer hier abweicht, baut ein Feld, das sich gegenüber jeder anderen Combobox im System falsch anfühlt.

Die Trefferzahl ansagen

Sehende sehen, dass drei Vorschläge erschienen sind. Alle anderen erfahren es nur über eine Live-Region:

function trefferMelden(anzahl) {
  status.textContent = anzahl === 0
    ? 'Keine Vorschläge'
    : `${anzahl} ${anzahl === 1 ? 'Vorschlag' : 'Vorschläge'} verfügbar`;
}

Zwei Feinheiten: Die Meldung gehört in ein role="status" (höflich, unterbricht nicht), und sie sollte entprellt werden. Wer bei jedem Tastendruck eine neue Ansage abfeuert, erzeugt einen Redeschwall statt einer Hilfe – 300 bis 500 Millisekunden Wartezeit nach der letzten Eingabe sind ein guter Wert.

Randnotiz – ein Muster, das man nicht raten sollte. Die Combobox ist eines der komplexesten ARIA-Muster. Hier lohnt es sich, die Referenzbeispiele des ARIA Authoring Practices Guide genau nachzubauen oder eine geprüfte Komponente zu nutzen, statt das Verhalten zu erfinden. Halb korrekte Comboboxen sind oft schlechter bedienbar als ein einfaches <select>.

aria-autocomplete und autocomplete – nicht dasselbe

Zwei ähnlich klingende Attribute mit völlig verschiedenen Aufgaben:

aria-autocomplete beschreibt, wie deine Komponente vervollständigt:

  • list – es erscheint eine Liste, das Feld bleibt unverändert (der Normalfall).
  • both – es erscheint eine Liste und der Rest des Wortes wird im Feld ergänzt und markiert.
  • none – keine Vervollständigung, nur eine feste Liste.

autocomplete ist das HTML-Attribut für den Browser-Autofill. autocomplete="off" verhindert, dass sich die gespeicherten Adressen des Browsers über deine Vorschlagsliste legen. Aber Vorsicht: Bei Feldern, die persönliche Daten der Nutzerin abfragen – Name, E-Mail, Straße, Postleitzahl –, verlangt 1.3.5 Eingabezweck bestimmen genau umgekehrt einen passenden Autofill-Token:

<!-- Ortsauswahl im Adressformular: Autofill NICHT abschalten -->
<input id="ort" name="ort" autocomplete="address-level2" role="combobox" />

<!-- Produktsuche: hier ist off richtig -->
<input id="suche" name="suche" autocomplete="off" role="combobox" />

Für Menschen mit kognitiven Einschränkungen ist der Autofill oft die eigentliche Hilfestellung. Ihn wegzuschalten, um die eigene Vorschlagsliste sauber aussehen zu lassen, ist ein schlechter Tausch.

Auf dem Handy

Zwei Dinge ändern sich auf Touchgeräten grundlegend. Erstens öffnet die Bildschirmtastatur und lässt oft nur noch ein Drittel der Höhe für die Liste übrig – eine Vorschlagsliste unterhalb des Feldes kann dann komplett verdeckt sein. Zweitens funktioniert aria-activedescendant mit Touch-Screenreadern erfahrungsgemäß schlechter als am Desktop; VoiceOver auf iOS ignoriert es weitgehend.

Praktische Folge: Die Vorschläge müssen auch dann bedienbar sein, wenn sie einzeln angetippt werden – also echte, ausreichend große Ziele (24 × 24 CSS-Pixel nach 2.5.8), und ein Feld, das ohne Auswahl aus der Liste ebenso funktioniert.

Und der Datepicker?

Erst die native Variante prüfen: <input type="date"> bringt einen tastaturbedienbaren, lokalisierten Kalender mit. Nur wenn echte Sonderwünsche (Zeiträume, gesperrte Tage) das verlangen, baust du einen eigenen – dann mit dem Grid-Pattern und vollständiger Tastatursteuerung. Vorher gilt: Lässt sich das Datum auch einfach eintippen? Oft ja. Alle drei Wege – nativ, Textfeld, APG-Kalender-Dialog – vergleicht ausführlich die Seite Datums- & Zeitauswahl (Datepicker).

Häufige Fehler

  • Eigene Combobox ohne Tastatur (nur Maus/Klick auf Vorschläge).
  • role="combobox" am Wrapper statt am Eingabefeld – die veraltete ARIA-1.1-Form.
  • aria-expanded nicht gepflegt – die Ansage „auf/zu“ stimmt nicht.
  • Fokus in die Liste verschoben statt mit aria-activedescendant im Feld zu bleiben.
  • aria-activedescendant auf ein Element außerhalb der Liste – bringt Windows-Screenreader zwischen den Modi durcheinander.
  • Kein scrollIntoView – die hervorgehobene Option bleibt außerhalb des sichtbaren Bereichs.
  • Keine Trefferansage – sehende sehen die Liste, andere nicht.
  • Ansage bei jedem Tastendruck statt entprellt – ein Redeschwall.
  • autocomplete="off" an Adress- und Namensfeldern – Konflikt mit 1.3.5.
  • Eigener Datepicker, wo <input type="date"> gereicht hätte.

Wie weit die native Variante trägt, zeigt der Komponenten-Baukasten: <datalist> gegen ARIA-Combobox, mit Vorschau, Code und Testprotokoll für beide Wege.

Häufige Fragen

<datalist> oder eigenes Combobox-Pattern?

<datalist>, wann immer es reicht – es ist robust und kostenlos. Zum ARIA-Muster greifst du erst bei echtem Bedarf an Filterung, Gestaltung oder Gruppierung. Faustregel: Wenn Tippen ohne Auswahl aus der Liste auch zum Ziel führt, reicht <datalist>.

Warum autocomplete="off" an der Combobox?

Damit sich der Browser-eigene Autofill nicht mit deiner Vorschlagsliste überlagert. Setze es aber nur, wo das Feld keinen Autofill-Zweck hat – bei Name, Adresse oder E-Mail verlangt WCAG 1.3.5 das Gegenteil.

Ist ein <select> nicht einfacher?

Oft ja. Für eine reine Auswahl aus überschaubaren Optionen ist <select> die einfachste, robusteste Wahl – und seit appearance: base-select auch gestaltbar. Combobox lohnt erst, wenn Tippen und Filtern echten Mehrwert bringen.

Muss die Liste ein <ul> sein?

Nein. role="listbox" und role="option" überschreiben die Listensemantik ohnehin. Wichtig ist nur, dass zwischen Listbox und Optionen kein Element mit eigener Rolle steht – ein <div role="listbox"> mit direkten <div role="option">-Kindern ist genauso gültig.

Wie sage ich „keine Treffer“ an?

Über dieselbe Live-Region wie die Trefferzahl. Wichtig ist, dass aria-expanded dann auf false steht, wenn wirklich keine Liste zu sehen ist – oder auf true, wenn du einen sichtbaren „Keine Treffer“-Eintrag anzeigst. Der Eintrag braucht dann role="option" und darf nicht auswählbar sein.

Reicht ein automatischer Test?

Nein. Automatische Prüfwerkzeuge finden fehlende Rollen, aber nicht das Wesentliche: ob aria-expanded mitläuft, ob die Ansage kommt, ob Escape zweistufig funktioniert. Diese Komponente muss man mit Screenreader und Tastatur durchspielen – siehe Mit NVDA testen.

Fazit

Für Vorschlagsfelder gilt eine klare Reihenfolge: erst <datalist>, bei reiner Auswahl <select> (heute auch gestaltbar), und erst bei echtem Bedarf das ARIA-Combobox-Pattern. Wer es baut, braucht vier Dinge korrekt: role="combobox" am Eingabefeld, ein aria-expanded, das immer stimmt, aria-activedescendant statt Fokusverschiebung – mit scrollIntoView, weil der Browser das nicht übernimmt – und eine entprellte Trefferansage per Live-Region. Weil die Combobox so anspruchsvoll ist, lohnt sich hier mehr als anderswo ein geprüftes Vorbild statt Eigenbau.

Quellen

Gratis E-Book PDF Das Praxishandbuch

Kostenloses E-Book

Das Praxishandbuch für sauberes, zugängliches Web

Alles rund um semantisches HTML, Barrierefreiheit, WCAG & BFSG, GEO und SEO — praxisnah und am echten Code. In mehreren Feedbackschleifen von Leserinnen und Lesern verbessert.

  • 3.000+ Downloads
  • 7. Auflage
  • 37 Seiten
  • PDF

Kein Spam. Abmeldung jederzeit mit einem Klick möglich.