Table of Contents
Die Herausforderung der Datumseingabe im Web
Die Datumsauswahl ist eine der häufigsten und dennoch frustrierendsten Interaktionen im Web. Native Browser Date Picker variieren stark zwischen den Plattformen und der Standard bietet eine begrenzte Styling-Kontrolle und inkonsistentes Tastaturverhalten. Der Aufbau eines benutzerdefinierten Datumspickers gibt Ihnen die volle Kontrolle über Aussehen, Verhalten und Zugänglichkeit. Wenn es richtig gemacht wird, wird es zu einer integrativen Komponente, die Benutzern unabhängig von ihrem Gerät, ihrer Eingabemethode oder ihrer unterstützenden Technologie dient.
Bei einem zugänglichen Datumswähler geht es nicht nur um die Einhaltung der WCAG-Richtlinien. Es wirkt sich direkt auf echte Benutzer aus: Menschen, die mit Tastaturen navigieren, diejenigen, die auf Bildschirmleser angewiesen sind, Personen mit motorischen Beeinträchtigungen, die Schaltgeräte verwenden, und alle, die von klaren visuellen Hinweisen profitieren. Die hier behandelten Techniken gelten für jedes JavaScript-Framework, aber die Beispiele verwenden Vanilla-Javascript, damit Sie sie an React, Vue oder jede andere Umgebung anpassen können.
Accessibility Foundations für Date Pickers
WCAG Erfolgskriterien verstehen
Mehrere WCAG 2.1-Erfolgskriterien gelten direkt für Datumsauswahler. Keyboard-Zugänglichkeit (SC 2.1.1) erfordert, dass alle Funktionen über eine Tastaturschnittstelle bedienbar sind. Der Fokus sichtbar (SC 2.4.7) erfordert einen klaren Fokusindikator, damit die Benutzer wissen, welches Datum ausgewählt wird. Name, Rolle, Wert (SC 4.1.2) stellt sicher, dass unterstützende Technologien die Komponente und ihren aktuellen Zustand identifizieren können. Der ARIA Authoring Practices Guide bietet ein Dialogmuster, das als Grundlage für Kalender-Widgets dient.
Semantisches HTML als Backbone
Beginnen Sie mit semantischen HTML-Elementen statt mit generischen s. Das Kalenderraster sollte ein -Element verwenden, weil es semantisch tabellarische Daten darstellt. Jede Datumszelle sollte ein -Element sein, das von Natur aus fokussierbar und über die Tastatur aktivierbar ist. Vermeiden Sie die Verwendung von -Elementen als interaktive Ziele, da sie keine native Tastaturunterstützung haben und zusätzliche ARIA benötigen, um Interaktivität zu kommunizieren. Eine solide semantische Grundlage reduziert die Menge an ARIA, die Sie hinzufügen müssen, und schafft eine robustere Erfahrung über unterstützende Technologien hinweg.
Architektur der Date Picker-Komponente
Kernelement der Benutzerschnittstelle
Ein kompletter Datumswähler benötigt diese visuellen und funktionalen Komponenten:
- Ein Texteingabefeld, das das ausgewählte Datum anzeigt und das Popup des Kalenders auslöst
- Ein Kalender-Popup mit einem Monats- / Jahres-Header, Navigationsschaltflächen für wechselnde Monate und einem Raster von Tagen
- Das heutige Datum wird visuell zur Orientierung hervorgehoben
- Das gewählte Datum ist deutlich mit einem bestimmten Stil gekennzeichnet
- Eine klare Schaltfläche oder Escape-Taste, um den Kalender zu verwerfen, ohne
Staatliche Verwaltung
Intern muss der Datumswähler mehrere Statusteile verfolgen: das aktuell fokussierte Datum (das vom ausgewählten Datum abweichen kann), den sichtbaren Monat und das sichtbare Jahr, den ausgewählten Datumswert und ob das Kalender-Popup geöffnet oder geschlossen ist. Diese müssen als JavaScript-Variablen beibehalten und die DOM- und ARIA-Attribute als Reaktion auf Zustandsänderungen aktualisiert werden.
Aufbau der HTML-Struktur für Zugänglichkeit
Das Input-Feld
Das Eingabefeld ist der primäre Interaktionspunkt des Benutzers und sollte seinen Zweck und seine Beziehung zum Kalender-Popup mithilfe von ARIA-Attributen kommunizieren:
Zugängliches Eingabebeispiel:
<label for="date-picker-input">Departure date</label>
<input type="text"
id="date-picker-input"
role="combobox"
aria-haspopup="dialog"
aria-expanded="false"
aria-controls="datepicker-calendar"
aria-autocomplete="none"
readonly
placeholder="MM/DD/YYYY">
Das -Muster signalisiert assistiven Technologien, dass diese Eingabe ein Popup steuert. Das -Attribut spiegelt dynamisch wider, ob der Kalender sichtbar ist. Das Einstellen der Eingabe als verhindert manuelle Texteingabe, während Tastaturfokus und Klickereignisse ermöglicht werden. Für Implementierungen, die eine direkte Datumseingabe ermöglichen, fügen Sie Validierungslogik und -Zustandsverwaltung hinzu.
Der Kalender-Dialog
Das Kalender-Popup folgt dem dialog Muster aus ARIA Authoring Practices. Es sollte als Geschwister zum Eingabefeld im DOM gerendert werden, typischerweise in einem Container, der die Positionierung übernimmt:
<div id="datepicker-calendar"
role="dialog"
aria-modal="true"
aria-label="Choose a date"
hidden>
<div class="calendar-header">
<button class="prev-month" aria-label="Previous month">‹</button>
<h3 id="calendar-month-year" aria-live="polite">January 2025</h3>
<button class="next-month" aria-label="Next month">›</button>
</div>
<table class="calendar-grid" role="grid" aria-labelledby="calendar-month-year">
<thead>
<tr>
<th scope="col"><abbr title="Sunday">Sun</abbr></th>
<th scope="col"><abbr title="Monday">Mon</abbr></th>
<th scope="col"><abbr title="Tuesday">Tue</abbr></th>
<th scope="col"><abbr title="Wednesday">Wed</abbr></th>
<th scope="col"><abbr title="Thursday">Thu</abbr></th>
<th scope="col"><abbr title="Friday">Fri</abbr></th>
<th scope="col"><abbr title="Saturday">Sat</abbr></th>
</tr>
</thead>
<tbody>
<!-- Date rows rendered dynamically -->
</tbody>
</table>
<div class="calendar-footer">
<button class="today-button">Today</button>
</div>
</div>
Die auf der Tabelle bietet eine optimierte Navigation für Bildschirmleser in tabellarischen Layouts. Jede Datumszelle sollte ein -Element sein, wobei explizit angewendet wird, wenn ein nicht semantisches Element verwendet wird. Die -Region in der Überschrift Monat/Jahr stellt sicher, dass Bildschirmleser Monatänderungen ankündigen, ohne den Benutzer zu unterbrechen.
Implementierung von Tastaturnavigation
Fokusmanagementstrategie
Wenn der Kalender geöffnet wird, wird der Fokus auf das aktuell ausgewählte Datum oder auf das heutige Datum verschoben, wenn keine Auswahl existiert. Dies folgt dem Autofokusdialog Muster. Der Kalender sollte den Fokus während des Öffnens in sich selbst einfangen, wodurch der Benutzer nicht auf Elemente hinter dem Popup tippen kann. Implementieren Sie eine Fokusfalle, die zwischen dem ersten und dem letzten fokussierbaren Element innerhalb des Dialogs zykliert.
Keyboard Event Mapping
Datumsauswahl erfordert eine konsistente Tastaturoberfläche. Das ARIA-Raster definiert Standard-Key-Mappings für die Navigation in tabellarischen Inhalten:
- Pfeiltasten verschieben den Fokus einen Tag in die entsprechende Richtung. Wenn sich der Fokus über den aktuellen Monat hinaus bewegt, wechselt der Kalender automatisch in den angrenzenden Monat.
- Home und End verschieben den Fokus auf den ersten oder letzten Tag des aktuellen Monats.
- Page Up und Page Down navigieren zum vorherigen oder nächsten Monat, während der Tag des Monats beibehalten wird (bei Bedarf am letzten Tag des Zielmonats eingeklemmt).
- Enter or Space wählt das aktuell fokussierte Datum aus und schließt den Kalender.
- Escape schließt den Kalender und gibt den Fokus zum Eingabefeld zurück.
- Tab bewegt den Fokus innerhalb der Dialogkomponenten (Monatsnavigationstasten, Raster, heute Schaltfläche).
Verwaltung von Roving-Tabindex
Wenn Sie dies tun, können Sie dies tun, indem Sie dies tun, um dies zu tun.
ARIA Attribute für Screen Reader Support
Dynamische ARIA Staatsführung
Bildschirmleser verlassen sich auf ARIA-Attribute, um Zustandsänderungen zu kommunizieren. Aktualisieren Sie diese Attribute in Echtzeit, während der Benutzer mit der Datumsauswahl interagiert:
- aria-expanded] auf dem Eingang: gesetzt zu wenn der Kalender öffnet, wenn er schließt.
- aria-hidden im Kalenderdialog: entfernen (), wenn sichtbar, hinzufügen (, wenn versteckt.
- aria-selected auf der ausgewählten Datumstaste: gesetzt auf auf dem gewählten Datum, auf allen anderen. Beachten Sie, dass Tasten nativ einen gedrückten Zustand unterstützen, aber das richtige Attribut für Gitterzellenrollen ist.
- aria-activedescendant auf der Eingabe: zeigen Sie auf die ID der aktuell fokussierten Datumszelle.
- aria-label auf jedem Datumsbutton: fügen Sie das vollständige Datum ein, wie "Januar 15, 2025" und nicht nur "15".
Bekanntgabe von Kontextänderungen
Wenn der Benutzer zu einem neuen Monat navigiert, geben Sie den Monat und das Jahr mit einer Live-Region an. Viele Implementierungen aktualisieren die im Dialog oder verwenden eine visuell verborgene -Region. Wenn ein Datum ausgewählt ist, geben Sie "Januar 15, 2025 ausgewählt" an, um die Aktion zu bestätigen. Geben Sie eine -Region für kritische Bestätigungen und für weniger dringende Updates wie Monatsänderungen an.
JavaScript Implementierung Details
Initialisierung und Konfiguration
Erstellen Sie eine DatePicker-Klasse oder Werksfunktion, die Konfigurationsoptionen akzeptiert: das Eingabeelement, das Datumsformat, die minimalen und maximalen Daten und die Rückruffunktionen für die Datumsauswahl. Initialisieren Sie, indem Sie Ereignishörer auf der Eingabe einrichten und den ursprünglichen Kalendermonat rendern:
class AccessibleDatePicker {
constructor(input, options = {}) {
this.input = input;
this.options = Object.assign({
format: 'MM/DD/YYYY',
minDate: null,
maxDate: null,
onDateSelect: () => {}
}, options);
this.selectedDate = null;
this.focusedDate = null;
this.currentMonth = new Date().getMonth();
this.currentYear = new Date().getFullYear();
this.isOpen = false;
this.calendar = this.buildCalendarElement();
this.setupEventListeners();
}
// ... methods
}
Rendern des Kalender-Gitters
Die Renderfunktion berechnet den ersten Tag des Monats, die Anzahl der Tage im Monat und alle Tage, die vom vorherigen und nächsten Monat zurückliegen, um das Raster zu füllen. Jede Datumsschaltfläche erhält Datenattribute für die Datumskomponenten und eine mit dem vom Menschen lesbaren Datum:
renderMonth() {
const firstDay = new Date(this.currentYear, this.currentMonth, 1).getDay();
const daysInMonth = new Date(this.currentYear, this.currentMonth + 1, 0).getDate();
const daysInPrevMonth = new Date(this.currentYear, this.currentMonth, 0).getDate();
let cells = [];
// Add trailing days from previous month
for (let i = firstDay - 1; i >= 0; i--) {
cells.push(this.createDateButton(daysInPrevMonth - i, this.currentMonth - 1, this.currentYear, true));
}
// Add days of current month
for (let day = 1; day <= daysInMonth; day++) {
cells.push(this.createDateButton(day, this.currentMonth, this.currentYear));
}
// Add leading days of next month
const remaining = 42 - cells.length; // 6 rows × 7 columns
for (let day = 1; day <= remaining; day++) {
cells.push(this.createDateButton(day, this.currentMonth + 1, this.currentYear, true));
}
// Render into table body...
}
Event-Delegation für Dynamische Inhalte
Anstatt Ereignis-Listener einzeln an jede Datumstaste anzubringen, verwenden Sie Ereignisdelegation auf dem Rastercontainer. Hören Sie auf -Ereignisse auf dem -Element und bestimmen Sie, welches Datum mit angeklickt wurde. Dieser Ansatz verarbeitet dynamisch generierte Daten, ohne die Zuhörer wieder anzuhängen und reduziert die Speicherauslastung.
Datumsauswahl Flow
Wenn ein Benutzer ein Datum auswählt, formatiert die Komponente das Datum entsprechend dem konfigurierten Format, aktualisiert den Eingabewert, speichert das ausgewählte Datum intern und ruft den -Rückruf auf. Nach der Auswahl schließt der Kalender und kehrt zum Eingang zurück. Aktualisieren Sie das -Attribut für die zuvor ausgewählte Zelle zu und für die neu ausgewählte Zelle zu . Auslösen Sie ein benutzerdefiniertes -Ereignis auf dem Eingabeelement, damit andere Skripte, die auf Änderungen hören, reagieren können.
Visuelles Styling für Zugänglichkeit
Kontrast und Farbunabhängigkeit
Farbe sollte niemals der einzige Indikator für den Zustand sein. Verwenden Sie eine Kombination aus Hintergrundfarbe, Textfarbe, Rahmen und Textdekoration, um ausgewählte, fokussierte und deaktivierte Zustände zu kommunizieren. Behalten Sie ein Mindestkontrastverhältnis von 3:1 für Nicht-Text-Inhalte und 4,5:1 für Textinhalte gemäß WCAG SC 1.4.3 und 1.4.11. Geben Sie einen -Hochkontrastmodus an, der fette Grenzen und Unterstriche anstelle von subtilen Farbänderungen verwendet.
Design von Fokusindikatoren
Der Fokusindikator muss gegen alle umgebenden Elemente sichtbar sein. Verwenden Sie eine oder mit ausreichender Dicke und Kontrast. Vermeiden Sie es, die Standard-Browserumrisse zu entfernen, ohne einen Ersatz bereitzustellen. Ein 3-Pixel-Durchschnitt mit einer Farbe, die sowohl gegen den Standardhintergrund als auch gegen den ausgewählten Zustand kontrastiert, sorgt für Sichtbarkeit. Testen Sie den Fokusindikator mit dem ausgewählten Datumszustand, dem deaktivierten Zustand und dem Hover-Zustand, um zu bestätigen, dass er unterscheidbar bleibt.
Touch Target-Größe
Jede Datumsschaltfläche sollte ein Mindest-Touch-Ziel von 44x44 CSS-Pixeln haben, wie von WCAG SC 2.5.8 empfohlen. Dies gilt für mobile Geräte, Tablets und Benutzer mit geringer Fingerfertigkeit, die Touch- oder Stylus-Eingaben verwenden können. Stellen Sie sicher, dass die Monatsnavigationsschaltflächen und die Heute-Schaltfläche auch diese Mindestabmessungen erfüllen. Wenn Platzbeschränkungen kleinere Ziele erfordern, bieten Sie visuelle Polsterung oder vergrößern Sie den anklickbaren Bereich mit Pseudo-Elementen.
Testen Sie Ihren Date Picker auf Zugänglichkeit
Manuelle Tastaturprüfung
Testen Sie die Komponente nur mit einer Tastatur. Tabuisieren Sie sich in der Eingabe, öffnen Sie den Kalender mit Enter oder Space und navigieren Sie mit Pfeiltasten durch alle Daten. Stellen Sie sicher, dass Escape das Popup schließt und den Fokus auf die Eingabe zurückgibt. Stellen Sie sicher, dass die Fokusanzeige jederzeit sichtbar ist und dass die Fokusreihenfolge dem visuellen Layout folgt. Testen Sie mit Page Up, Page Down, Home und End, um sicherzustellen, dass sie die erwartete Monats- und Tagesnavigation ausführen. Dokumentieren Sie jedes unerwartete Verhalten und beheben Sie es, bevor Sie die Komponente als vollständig betrachten.
Screen Reader Testing
Testen Sie mit mindestens zwei Bildschirmlesern. Eine Kombination von NVDA (kostenlos) mit Firefox und JAWS (kommerziell) mit Chrome deckt die Mehrheit der Bildschirmleser ab. Stellen Sie sicher, dass der Bildschirmleser die Dialogrolle, den Monat und das Jahr und das Datum während der Navigation des Benutzers ankündigt. Bestätigen Sie, dass der Status angekündigt und das ausgewählte Datum mitgeteilt wird, wenn der Dialog geöffnet wird. Testen Sie mit einem Bildschirmleser auf einem mobilen Gerät mit TalkBack (Android) oder VoiceOver (iOS), um sicherzustellen, dass die Touch-Navigation funktioniert.
Automatisierte Testing Tools
Verwenden Sie automatisierte Tools wie axe DevTools oder Lighthouse, um allgemeine Barrierefreiheitsprobleme zu erkennen. Diese Tools können fehlende ARIA-Attribute, unzureichenden Farbkontrast und fehlende Labels identifizieren. Automatisierte Tests können jedoch nicht alle Probleme erkennen. Manuelles Testen bleibt unerlässlich für die Bewertung von Bildschirmleser-Ankündigungen, Tastaturfluss und Benutzerfreundlichkeit in der realen Welt. Integration von Barrierefreiheitstests in Ihre kontinuierliche Integrationspipeline mit Tools wie axe-core, um Regressionen frühzeitig zu erkennen.
Real-World Integration Überlegungen
Internationalisierung und Lokalisierung
Datumsauswahlen dienen einem globalen Publikum. Unterstützen Sie mehrere Gebietsschemata, indem Sie die -API verwenden, um Datums- und Monatsnamen zu formatieren. Ermöglichen Sie die Konfiguration des ersten Wochentags (Sonntag vs. Montag) basierend auf dem Gebietsschema. Rendern Sie Wochentags-Header mit abgekürzten Namen, die das Gebietsschema respektieren. Geben Sie Übersetzungen für ARIA-Labels wie "Vorheriger Monat" und "Wählen Sie ein Datum" an. Die Intl.DateTimeFormat-Dokumentation bietet umfassende Anleitungen zur lokal-bewussten Datumsformatierung.
Touch und Mobile Optimierung
Auf mobilen Geräten ist der Kalenderdialog so zu positionieren, dass Überlappungen mit der virtuellen Tastatur vermieden werden; es ist in Betracht zu ziehen, auf kleinen Bildschirmen einen Vollbild-Modal für den Kalender zu verwenden, wobei der gesamte Viewport der Datumsauswahloberfläche gewidmet ist; Swipe-Gesten für die Monatsnavigation als progressive Erweiterung zu implementieren; Testen Sie auf tatsächlichen mobilen Geräten mit Touch- und Screenreader-Eingaben, um zu bestätigen, dass Touch-Ziele groß genug sind und dass Gestenaktionen zugängliche Rückgriffe haben.
Performance und Bundle Size
Eine benutzerdefinierte Datumsauswahl sollte Ihre Anwendung nicht aufblähen. Halten Sie das JavaScript-Bundle unter 10 KB verkleinert und gzipped, indem Sie unnötige Abhängigkeiten vermeiden und effizienten Code schreiben. Verwenden Sie Schließungen und Werksfunktionen, um Klassenvererbung zu vermeiden. Lazy-initialisieren Sie den Kalender-DOM nur, wenn der Benutzer den Picker zum ersten Mal öffnet, anstatt ihn beim Seitenladen zu erstellen. Bereinigen Sie Ereignis-Listener und DOM-Referenzen, wenn die Komponente zerstört wird, um Speicherlecks in einseitigen Anwendungen zu verhindern.
Handhabung von Kantengehäusen
Disabled und Restricted Dates
Implementieren Sie eine -Funktion, die mit Min/Max-Daten, Wochentagsbeschränkungen und benutzerdefinierten Ausschlussregeln abgleicht. Deaktivierte Daten sollten erhalten und von der Tastaturnavigation ausgeschlossen werden. Visuell sollten deaktivierte Daten eine reduzierte Opazität verwenden und Hover-Effekte vermeiden. Wenn ein Benutzer durch das Raster läuft, überspringen Sie deaktivierte Daten vollständig. Geben Sie einen Hinweis oder Tooltip an, der erklärt, warum ein Datum nicht verfügbar ist, zugänglich über .
Nullwerte und klare Handlungen
Unterstützen Sie das Löschen des ausgewählten Datums, indem Sie eine Schaltfläche in der Kalenderfußzeile freigeben oder dem Benutzer erlauben, erneut auf das aktuell ausgewählte Datum zu klicken. Wenn kein Datum ausgewählt ist, sollte der Eingabeplatzhalter das erwartete Format mitteilen. Der Kalender sollte sich öffnen und den aktuellen Monat ohne Datum anzeigen, aber mit Fokus auf das heutige Datum für die Orientierung. Beharren Sie auf dem letzten ausgewählten Monat, so dass der Benutzer, wenn er den Kalender erneut öffnet, zu dem Monat zurückkehrt, den er zuvor angesehen hat.
Browser und Framework-Kompatibilität
Testen Sie den Datumswähler über Chrome, Firefox, Safari und Edge. Achten Sie besonders auf Safari, das in der Vergangenheit inkonsistente Fokusindikator-Unterstützung hatte. Verwenden Sie , um Fokusindikatoren nur dann bereitzustellen, wenn der Benutzer über die Tastatur navigiert und persistente Umrisse bei Klick-Interaktionen vermeidet. Für Frameworks wie React wickeln Sie den Datumswähler in einen benutzerdefinierten Haken, der den Zustand und den Lebenszyklus durch und verwaltet. Verwenden Sie und , um auf Prop-Änderungen und Eingabeereignisse zu reagieren.
Alles zusammensetzen
Ein zugänglicher Datumswähler basiert auf semantischem HTML, sorgfältiger ARIA-Verwaltung und robustem Tastaturereignishandling. Das Eingabefeld verwendet Combobox-Semantik, um seine Beziehung zum Kalenderdialog zu kommunizieren. Das Datumsraster folgt dem Roving-Tabindex-Muster für eine effiziente Tastaturnavigation. ARIA-Attribute werden dynamisch aktualisiert, um den aktuellen Zustand widerzuspiegeln, Bildschirmleser erhalten Kontextankündigungen durch Live-Regionen, und das visuelle Design behält ausreichend Kontrast und klare Fokusindikatoren bei.
Der wahre Maßstab für den Erfolg ist nicht, wie viele ARIA-Attribute Sie hinzufügen, sondern wie nahtlos sich das Erlebnis für Benutzer von assistierender Technologie anfühlt. Ein gut gebauter Datumswähler sollte sich für einen Tastaturbenutzer genauso natürlich anfühlen wie für einen Mausbenutzer. Indem Sie den hier beschriebenen Mustern folgen und gründlich mit echten assistiven Technologien testen, erstellen Sie eine Komponente, die allen dient.
Die Zugänglichkeit ist kein Feature-Kipper oder ein letzter Schritt. Sie ist ein integraler Bestandteil des Design- und Entwicklungsprozesses. Wenn Sie von Anfang an mit Zugänglichkeit bauen, vermeiden Sie kostspielige Refactorings und bieten ein besseres Erlebnis für alle Benutzer. Die Datumsauswahl ist nur eine Komponente, aber die Prinzipien, die Sie hier anwenden, tragen jedes interaktive Element mit sich, das Sie erstellen.