Komponenten · Formulare

Datums- & Zeitauswahl (Datepicker) barrierefrei

Die zugänglichste Datumseingabe ist fast immer ein Textfeld mit sichtbarer Formatangabe oder ein natives input type="date" – beides liefert Tastaturbedienung und Screenreader-Anbindung ohne eine Zeile ARIA. Ein Kalender-Widget ist ein Zusatzweg für Fälle, in denen der Kalender selbst Information trägt, und niemals der einzige Eingabeweg.

Kaum eine Komponente wird so oft neu und so oft unzugänglich gebaut wie der Datepicker. Dabei liegt der wichtigste Schritt vor der Technik: Wer sein Geburtsdatum eingibt, will tippen und nicht vierzig Jahre zurückblättern. Wer ein Hotel bucht, will den Wochentag und freie Nächte sehen. Das sind zwei verschiedene Aufgaben – und sie brauchen zwei verschiedene Lösungen.

Das Wichtigste in Kürze

  • Rangfolge: Textfeld mit klarem Format → natives input type="date" → Kalender-Dialog nach ARIA APG. Je weiter hinten, desto mehr Verantwortung für Fokus, Tastatur und Ansagen liegt bei dir.
  • Ein Kalender ersetzt nie die Tastatureingabe. Tippen muss immer möglich sein – für bekannte Daten ist es der schnellste Weg für alle.
  • Die Formatangabe gehört ins Label („Geburtsdatum (TT.MM.JJJJ)“), nicht in den Platzhalter. Platzhalter verschwinden beim Tippen und haben oft zu wenig Kontrast.
  • input type="date" überträgt immer ISO-Format (2026-07-24), zeigt aber das Datum in der Schreibweise des Systems an. Das ist ein Vorteil, kein Fehler.
  • Das Tastaturmodell des Kalender-Grids ist umfangreich: Pfeiltasten tageweise, Bild ↑/↓ monatsweise, Umschalt + Bild ↑/↓ jahresweise, Pos1/Ende Wochenanfang/-ende, Enter wählt, Esc schließt.
  • Tageszellen brauchen 24 × 24 Pixel und Markierungen mindestens 3:1 Kontrast – ein Kalender ist die Komponente mit den kleinsten Zielflächen im ganzen Formular.
  • Nach der Auswahl bestätigt eine Statusmeldung das Ergebnis, und der Fokus kehrt zum Auslöser zurück.
  • Von Scroll-Rädchen für Uhrzeiten rate ich ab. Sie sind per Tastatur und Screenreader regelmäßig ein Totalausfall und verletzen 2.5.7, wenn nur Wischen funktioniert.
Drei Lösungswege für eine Datumseingabe nebeneinander, von links nach rechts numeriert. Erstens ein Textfeld mit dem Label Geburtsdatum in Klammern TT.MM.JJJJ, dem Wert 24.06.1985, einem sichtbaren Beispielhinweis und dem Attribut autocomplete bday; als Bewertung: Tippen bleibt der schnellste Weg, Screenreader behandeln es als normales Textfeld, die Eingabe muss tolerant geparst werden; Aufwand null Zeilen ARIA. Zweitens ein natives input type date mit dem Label Reisedatum, dem Wert 24.07.2026 und einem Kalendersymbol, min und max werden vom Browser geprüft, mobil erscheint die Systemoberfläche; als Bewertung: Tastatur und Ansagen kommen vom Browser, mobil dem Eigenbau überlegen, Optik kaum gestaltbar; Aufwand null Zeilen ARIA. Drittens ein Kalender-Dialog mit Eingabefeld, Monatskopf Juli 2026 und einem Wochenraster, in dem der 24. blau als ausgewählt und der 30. mit einem orangen Fokusrahmen markiert ist; als Bewertung: Wochentag und Belegung sichtbar, das Grid-Tastaturmodell und die Fokusführung müssen komplett selbst gebaut werden; Aufwand grid, gridcell, aria-selected, aria-modal und Roving Tabindex. Zwei Balkenreihen darunter vergleichen eigenen Testaufwand und Gestaltungsfreiheit: der Testaufwand steigt beim Dialog auf das Maximum.
Der Aufwand ist nicht gleichmäßig verteilt: Die ersten beiden Wege kosten null ARIA-Attribute, der dritte ein komplettes Tastaturmodell.

Weg 1: Das Textfeld mit klarem Format

Für bekannte Daten – Geburtsdatum, Rechnungsdatum, Vertragsbeginn – ist das Textfeld die schnellste und zugänglichste Lösung. Es gibt nichts zu bedienen, nur etwas zu tippen:

<label for="geburt">Geburtsdatum (TT.MM.JJJJ)</label>
<input
  id="geburt"
  name="geburt"
  type="text"
  inputmode="numeric"
  autocomplete="bday"
  aria-describedby="geburt-bsp"
/>
<p id="geburt-bsp">Zum Beispiel: 24.06.1985</p>

Vier Details entscheiden hier über Erfolg oder Frust:

Die Formatangabe steht sichtbar im Label. Nicht im placeholder – der verschwindet beim ersten Zeichen, hat in vielen Designs zu wenig Kontrast und ist für Menschen mit Gedächtniseinschränkungen genau dann weg, wenn er gebraucht wird. Das verlangt 3.3.2 Beschriftungen oder Anweisungen.

autocomplete setzen. Für Geburtsdaten gibt es bday und, wenn es drei Felder sein müssen, bday-day, bday-month, bday-year. Das ist keine Bequemlichkeit, sondern 1.3.5 Eingabezweck bestimmen – und für Menschen mit motorischen Einschränkungen der Unterschied zwischen zehn Tastendrücken und einem.

Tolerant parsen. 24.6.85, 24-06-1985, 24/06/1985, 24 06 1985 – all das ist eine klare Absicht. Wer davon nur eine Schreibweise annimmt, produziert Fehlermeldungen für korrekte Eingaben. Das Umformatieren nach dem Verlassen des Feldes ist erlaubt, muss aber sichtbar bleiben und darf den Wert nicht stillschweigend verändern.

Bei Fehlern konkret werden. Nicht „Ungültiges Datum“, sondern „Bitte im Format TT.MM.JJJJ eingeben, zum Beispiel 24.06.1985“ – das fordert 3.3.3 Fehlervorschlag. Wie Fehlermeldungen technisch angebunden werden, steht unter Fehlermeldungen barrierefrei.

Weg 2: Das native input type="date"

<label for="reise">Reisedatum</label>
<input type="date" id="reise" name="reise" min="2026-07-30" max="2027-07-30" />

Der Browser liefert Tastaturbedienung, Screenreader-Anbindung und mobil die passende Systemoberfläche – ohne eine Zeile JavaScript, ganz im Sinn der ersten Regel von ARIA.

Was dabei oft missverstanden wird: Das Feld zeigt das Datum in der Schreibweise, die das Betriebssystem des Nutzers vorgibt, und überträgt es immer als ISO-Datum (2026-07-24). Du musst also nichts lokalisieren und nichts parsen – zwei Fehlerquellen fallen komplett weg. Mit min, max und step übernimmt der Browser außerdem die Bereichsprüfung, inklusive Meldung in der Systemsprache.

Die Grenzen, ohne Beschönigung:

  • Die Optik lässt sich kaum beeinflussen. Der Kalender, den der Browser aufklappt, ist nicht gestaltbar; nur das Feld selbst ist es teilweise.
  • Die Erscheinung unterscheidet sich je Browser. Wer pixelgenaue Gleichheit über alle Systeme braucht, wird hier nicht glücklich.
  • Komplexe Anforderungen kann es nicht. Belegungskalender, Preis je Tag, Zeiträume mit Mindestdauer – dafür ist es nicht gebaut.
  • showPicker() öffnet die Browser-Auswahl per Skript, etwa aus einem eigenen Button. Praktisch, aber kein Ersatz für das Feld selbst: Es muss weiter tippbar bleiben.

Für die große Mehrheit der Formulare ist das trotzdem die richtige Wahl. Semantik und Verhalten sind nativ am robustesten, und der Wartungsaufwand liegt bei null.

Weg 3: Der Kalender-Dialog nach ARIA APG

Wenn der Kalender echten Mehrwert bietet – Verfügbarkeiten, Wochentag-Kontext, Preise je Tag –, dann als Ergänzung zum Eingabefeld, nie als Ersatz. Genau so beschreibt es das Muster „Date Picker Dialog“ im ARIA Authoring Practices Guide.

<label for="anreise">Anreise (TT.MM.JJJJ)</label>
<input id="anreise" name="anreise" type="text" inputmode="numeric" />
<button type="button" id="kal-auf" aria-label="Datum aus Kalender wählen">
  <span aria-hidden="true">▤</span>
</button>

<div role="dialog" aria-modal="true" aria-labelledby="kal-titel" hidden>
  <h2 id="kal-titel" aria-live="polite">Juli 2026</h2>
  <table role="grid">
    <thead>
      <tr><th scope="col" abbr="Montag">Mo</th>…</tr>
    </thead>
    <tbody>
      <tr>
        <td tabindex="-1" aria-selected="false" data-datum="2026-07-20">20</td>
        <td tabindex="0" aria-selected="true" data-datum="2026-07-24">24</td>

      </tr>
    </tbody>
  </table>
</div>

Das vollständige Tastaturmodell

Das ist der Teil, den fast jede Eigenbau-Lösung unvollständig lässt. Der APG schreibt für das Kalenderraster vor:

Taste Wirkung
/ einen Tag zurück / vor
/ eine Woche zurück / vor
Pos1 / Ende erster / letzter Tag der aktuellen Woche
Bild ↑ / Bild ↓ vorheriger / nächster Monat, Tagesnummer bleibt
Umschalt + Bild ↑/↓ vorheriges / nächstes Jahr
Enter / Leertaste Datum wählen, Dialog schließen, Feld füllen
Esc Dialog schließen, ohne zu wählen
Tab zwischen den Bedienelementen des Dialogs, im Kreis (Fokusfalle ist hier korrekt)

Dazu kommt das Roving Tabindex: Genau eine Tageszelle trägt tabindex="0", alle anderen tabindex="-1". So ist das Raster ein einziger Tabstop, und innerhalb bewegt man sich mit Pfeiltasten. Beim Monatswechsel über Bild ↑/↓ bleibt die Tagesnummer erhalten – oder rutscht auf den letzten Tag des Monats, wenn es den 31. dort nicht gibt.

Rollen, Zustände und Ansagen

  • Der Dialog ist ein role="dialog" mit aria-modal="true". Der Fokus wandert hinein, Esc schließt und gibt den Fokus an den Auslöser zurück. Alles, was für Dialoge und Modals gilt, gilt hier auch.
  • Das Raster ist ein role="grid" mit Wochentagen als Spaltenköpfe und Tagen als gridcell. Die Wochentag-Kürzel bekommen ein abbr-Attribut mit dem ausgeschriebenen Namen, damit „Mo“ nicht als Silbe vorgelesen wird.
  • Der ausgewählte Tag trägt aria-selected="true", und zwar nur einer. Der Zustand darf nicht allein an der Farbe hängen – ein Rahmen, eine Form oder ein zusätzliches Zeichen gehört dazu.
  • Die Monatsüberschrift ist eine höfliche Live-Region. Beim Blättern wird „August 2026“ angesagt, ohne dass der Fokus springt.
  • Nach der Auswahl bestätigt eine Statusmeldung das Ergebnis: „Gewählt: Freitag, 24. Juli 2026“. Und der Name des Auslöser-Buttons wechselt mit – aus „Datum aus Kalender wählen“ wird „Datum ändern, 24. Juli 2026“.
  • Gesperrte Tage brauchen einen Grund. aria-disabled="true" hält die Zelle fokussierbar und ansagbar; ein echtes disabled macht sie unsichtbar für die Navigation. Wer wissen will, warum der 3. August nicht wählbar ist, muss es hören können – „ausgebucht“ statt nur „nicht verfügbar“.

Das ist ein komplettes eigenes Widget. Selbst bauen lohnt fast nie; eine erprobte, APG-konforme Bibliothekskomponente mit genau diesem Tastaturmodell ist hier die vernünftige Wahl. Und die Prüffrage beim Auswählen einer Bibliothek ist immer dieselbe: Funktionieren Bild ↑/↓ und Umschalt + Bild ↑/↓? Daran scheitern die meisten.

Zeiträume: zwei Felder, kein Wunderwidget

Anreise und Abreise, Von und Bis, Zeitraum von Berichten – das sind zwei Datumsfelder, und zwar auch dann, wenn der Kalender optisch beide in einem Raster markiert. Was dabei regelmäßig fehlt:

  • Beide Felder haben ein eigenes Label und sind einzeln tippbar.
  • Nach der ersten Auswahl sagt eine Statusmeldung den Stand an („Anreise 24. Juli 2026 gewählt, jetzt Abreise wählen“).
  • Ist der Zeitraum vollständig, wird die Dauer genannt („24. bis 27. Juli 2026, 3 Nächte“).
  • Die Abhängigkeit ist programmatisch da: min am Abreisefeld folgt dem Anreisedatum.

Ich würd solche Strecken immer mit zwei Feldern beginnen und den Kalender darüberlegen – nicht umgekehrt. Wer mit dem Widget anfängt, baut die Felder am Ende als Attrappe nach.

Uhrzeiten

Für Zeiten gilt dieselbe Rangfolge: input type="time" zuerst, sonst Textfeld mit Format („HH:MM“). Das native Feld überträgt 14:30 und kennt min, max und step – letzteres ist der Weg zu Viertelstunden-Rastern.

Was ich im Web nicht empfehle, sind Scroll-Rädchen im Stil mobiler Betriebssysteme. In einer App sind sie systemseitig angebunden, im Browser sind sie ein Nachbau, der per Tastatur kaum und per Screenreader selten funktioniert. Und wenn sie nur auf Wischen reagieren, verstoßen sie gegen 2.5.7 Ziehbewegungen – jede Zieh-Funktion braucht einen Klick-Weg daneben.

So testest du es

  1. Nur Tastatur. Mit Tab ins Feld, tippen, absenden – ohne den Kalender zu benutzen. Funktioniert das nicht, ist alles andere zweitrangig.
  2. Kalender per Tastatur. Button mit Enter öffnen, mit Pfeiltasten navigieren, dann Bild ↓ und Umschalt + Bild ↓ probieren. Esc drücken: Landet der Fokus wieder auf dem Button?
  3. Mit Screenreader. In NVDA prüfen: Wird der ausgewählte Tag als „ausgewählt“ angesagt? Wird der Monatswechsel gemeldet? Kommt die Bestätigung nach der Auswahl an?
  4. Auf 200 % Zoom. Bleibt das Raster vollständig sichtbar, oder rutscht die Hälfte aus dem Bild? Kalender sind bei Vergrößerung besonders anfällig.
  5. Zielgrößen messen. Tageszellen mindestens 24 × 24 Pixel (2.5.8); bei sieben Spalten auf einem schmalen Viewport wird das schnell knapp.

Häufige Fehler

  • Kalender als einziger Eingabeweg – Tippen muss immer möglich sein.
  • Eigenbau-Grid ohne vollständiges Tastaturmodellrole="grid" ohne Bild ↑/↓ verspricht, was es nicht hält.
  • Format nur im Platzhalter – verschwindet beim Tippen.
  • Icon-Button ohne Namen – das Kalendersymbol braucht ein Label.
  • Fokus bleibt nach dem Schließen verloren statt zum Auslöser zurückzukehren.
  • Kalender öffnet beim Fokussieren des Feldes – ein Kontextwechsel bei Fokus, siehe 3.2.1, und er verdeckt das Feld, in das man gerade tippen wollte.
  • Gesperrte Tage ohne Grund und ohne Ansage.
  • Format-Strenge ohne Hilfe – „01/24/86 ist ungültig“ ohne Beispiel und Vorschlag.

Häufige Fragen

Warum nicht drei Selects (Tag / Monat / Jahr)?

Drei Felder heißt dreimal fokussieren, dreimal eine lange Liste durchsuchen – mit motorischen Einschränkungen mühsam, mit Screenreader zäh. Ein Textfeld mit toleranter Auswertung oder type="date" ist fast immer schneller. Wenn es Selects sein müssen, dann als Gruppe mit fieldset/legend und mit autocomplete="bday-day", bday-month, bday-year.

Unterstützen alle Browser input type="date"?

Alle aktuellen, ja – inklusive mobiler Systeme, wo die native Oberfläche den meisten Custom-Pickern überlegen ist. Uneinheitlich ist nur die Optik. Wer damit leben kann, spart sich das komplette Widget samt Tastaturmodell und Wartung.

Darf der Kalender beim Fokussieren des Feldes automatisch aufgehen?

Besser nicht. Er verdeckt genau das Feld, in das jemand tippen möchte, und ein selbsttätiger Wechsel bei Fokus ist ein Fall für 3.2.1. Ein eigener Button ist die verlässliche Lösung – dann entscheidet der Nutzer.

Wie kennzeichne ich nicht verfügbare Tage?

Mit aria-disabled="true" statt disabled, damit die Zelle beim Navigieren gefunden und angesagt wird, plus einer Begründung im zugänglichen Namen („3. August, ausgebucht“). Und visuell mit mehr als nur einer blassen Farbe – ein Durchstreichen oder Muster hilft.

Wo finde ich das offizielle Muster?

Im ARIA Authoring Practices Guide unter „Date Picker Dialog“ – mit Referenz-Implementierung und dem vollständigen Tastaturmodell. Es lohnt sich, das Beispiel einmal selbst mit der Tastatur durchzuspielen, bevor man eine Bibliothek auswählt.

Fazit

Die Rangfolge für Datumseingaben: Textfeld mit klarem Format oder natives type="date" zuerst, Kalender-Dialog nach APG als Zusatzweg. Die ersten beiden Wege kosten null ARIA-Attribute und liefern Tastatur, Ansagen und Bereichsprüfung vom Browser. Der dritte kostet ein komplettes Tastaturmodell, Fokusführung, Live-Region und Statusmeldung – und verdient sich das nur dort, wo der Kalender selbst Information trägt.

Wer trotzdem baut, prüft die zwei Stellen, an denen fast alle scheitern: Bild ↑/↓ für den Monatswechsel und der Fokus, der nach Esc zurückkommt. Die Formular-Grundlagen stehen in der Formular-Semantik, die verwandte Auswahl-Problematik bei den Comboboxen.

Quellen

  • Date Picker Dialog Example (W3C ARIA APG – Rollen, Roving Tabindex und das vollständige Tastaturmodell)
  • Datumswähler (BFIT-Bund, Handreichung „Barrierefreie Gestaltung von User-Interface-Elementen“ – Anforderungen an Tastatur, Kontrast und Zielgröße)
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.