Accessible Forms: Validation (Part 1)
UX bei der Formulareingabe verbessern:
- Pflichtfelder klar kennzeichnen
- Klare Instruktionen bereitstellen, wie die Inputs aussehen müssen
- Klare Benachrichtigungen, wenn die Formatierung nicht stimmt oder Informationen fehlen
- Klar kennzeichnen, welche Felder ungültig sind
- Klare Fehlermeldungen ausgeben, die eine Anleitung zur Korrektur bieten
Clientseitige vs. serverseitige Validierung
Client-Side: im Browser, bevor die Daten zum Server geschickt werden. Kann direkt beim oder nach dem Eintippen passieren. Sehr wichtiger Schritt, um einen unnötigen Schritt zum Server und zurück zu vermeiden.
Clientseitige Validierung ist kein Ersatz für serverseitige Validierung (weil clientseitig leicht umgangen werden kann).
Native HTML5 constraint validation
HTML5 stellt Attribute zur constraint validation zur Verfügung. Moderne Browser verwenden diese Attribute, um die Eingabe zu validieren:
<!-- indicates that the field is mandatory -->
<input type="email" required>
<!-- checks if the email-pattern is correct -->
<input type="email" required pattern="[...regex...]">
<!-- checks if the number of characters reaches or doesn't exceed a certain value -->
<input type="text" minlength="2" maxlength="20">
<!-- specifies the min and max allowed number value -->
<input type="number" min="0" max="100" step="5">
Wenn die Eingaben nicht den Erfordernissen entsprechen, schickt der Browser eine Fehlermeldung. Die Fehlermeldung ist browserabhängig und kann nicht per CSS gestaltet werden. Die Meldungen sind nicht über alle Browser konsistent und machen verschiedene andere Probleme: sie haben eventuell zuwenig Kontrast, sie skalieren nicht mit der Textgröße, wenn der User sie verstellt, sie verschwinden eventuell nach einer kurzen Zeit, ...
Man kann die Eingabefelder mit Pseudoklassen stylen: input:required, input:invalid, input:required, input:optional, input:valid.
Achtung, verschiedene Farben reichen nicht zur Kommunikation aus, rot-grün-Sehschwäche etc.!
Form validation with JavaScript
Zuerst muss man dem Formular sagen, dass es die browserseitige Validierung abschalten soll: <form novalidate> oder <button formnovalidate>.
JavaScript Constraint Validation API
Eigene oder eine verfügbare Library, sofern die accessible ist.
Voraussetzungen schaffen
Die beste Fehlervalidierung ist die Vermeidung von Fehlern im Vorfeld. Benutzer müssen ganz genau wissen, welche Felder wie auszufüllen sind. SC 3.3.2 Labels or Instructions sagt: Labels or instructions are provided when content requires user input.
Bezeichnung von Pflichtfeldern vs. optionalen Feldern
Kontroversielles Thema, zumindest jedes Pflichtfeld sollte deutlich gekennzeichnet werden. Optimalerweise enthält ein Formular nur Pflichtfelder – alles, was kein Pflichtfeld ist, ist eigentlich eine unnötige Information. Ein großangelegter Cart & Checkout Test hat ergeben, dass es zu vielen unnötigen Validierungen, Verwirrungen, einem langsameren Checkout-Prozess und sogar Abbrüchen kommt, wenn Pflichtfelder und optionale Felder nicht ausreichend gekennzeichnet sind. Es gibt auch entgegengesetzte Meinungen, die sagen, nur die optionalen Felder sollen gekennzeichnet werden. Es gibt keine one-fits-all Lösung, man muss ausprobieren, was in welchem Fall funktioniert. Die am wenigsten fehleranfällige Methode ist jedenfalls, beide Felder entsprechend zu kennzeichnen.
Pflichtfelder auszeichnen
Der robusteste Weg ist, Pflichtfeld einfach ins Label reinzuschreiben (ebenso optional).
Der Asterisk * sollte vermieden werden. Nicht alle User wissen, was das bedeutet. Wenn einer verwendet wird, dann sollte das vor dem Formular deutlich gekennzeichnet werden. Besser ist aber die Vermeidung, weil eh keiner die Instruktionen liest. (Gutes Design muss nicht erklärt werden!) Screenreader lesen das * auch als "Stern" vor, was völlig unpassend ist.
Es wäre möglich, das <abbr>-Element zu verwenden (siehe Video Minute 14/WCAG techniques). Man könnte ihn auch mit aria-hidden="true" vor dem Screenreader verstecken.
Soll ich das HTML-Attribut required verwenden oder aria-reqiured="true"? Normalerweise ist das native HTML-Element immer zu bevorzugen, aber der Nachteil ist, dass Screenreader dann immer invalid vorlesen, wenn man in das Input-Feld tabbt. Das ist eher ungünstig, daher kann man in diesem Fall auf das ARIA-Attribut ausweichen. Die Browserunterstützung ist in jedem Fall gut genug. Siehe dazu auch das Codebeispiel weiter unten (ungültige Eingaben kennzeichnen).
Eine Gruppe von Pflichtfeldern auszeichnen
Keinesfalls die einzelnen Optionen als required kennzeichnen, sondern die umgebende Gruppe. Das <fieldset> Element darf auch nicht mit required gekennzeichnet werden, da es auf die role="group" mappt, die ein strukturelles Element ist und kein interaktives: Lösung: wir überschreiben die ARIA-Role mit einer neuen Rolle, die auch ein required-field erlaubt. Achtung das funktioniert nur bei Radio-Buttons (nur ein Element auswählbar), nicht bei Checkboxen, bei denen es mehrere Auswahlen gibt.
<!-- this is valid 👍🏻 -->
<fieldset role="radiogroup" aria-required="true">
...
</fieldset>
<!-- this is not ⚠️ valid -->
<fieldset role="radiogroup" required>
...
</fieldset>
Hilfreiche Anleitungen zur Verfügung stellen
Kurze Anleitungen können Teil des Labes sein:
<label for="passw0rd">
Password (required)
<span>Your password should be at least 6 characcters long</span>
<input type="password" id="passw0rd">
</label>
Längere Anleitungen sollten als zusätzliche Beschreibung außerhalb des Labels zur Verfügung gestellt werden und programmatisch aria-describedby="..."mit dem Label verbunden werden. Dieser Text wird dann nach Name und Rolle vom Screenreader hinzugefügt. Screenreader machen eine kurze Pause zwischen Name und Rolle und der Beschreibung.
<label for="passw0rd">Create a password</label>
<input type="password" id="passw0rd" aria-describedby="passw0rd-requirements">
<div id="passw0rd-requirements">
<p>Your password should be: </p>
<ul>
<li>At least 12 characters – the more characters the better.</li>
<li>A mixture of both uppercase and lowercase letters.</li>
<li>A mixture aof letters and numbers.</li>
<li>Including at least one special character, e.g., ! Q # ? ]</li>
</ul>
</div>
Ungültige Felder/Eingaben kennzeichnen
Wenn Pflichtfelder leer bleiben oder die Eingaben nicht dem erwarteten Format entsprechen, das Formular aber trotzdem abgesendet wird, kommt es zu einem Eingabefeher (input error). Wenn das passiert, sollte genau ersichtlich sein, welche Felder betroffen sind und warum SC 3.3.1 Error Identification.
Relevante Success Criteria
- SC 3.3.1 Error Identification (Level A)
- If an input error is automatically detected, the item that is in error is identified and the error is described to the user in text.
Es gibt kein natives HTML-Element, das ein ungültiges Feld kennzeichnet. Wir greifen hier wieder auf ARIA zurück. Aber Vorsicht: Das Feld sollte keinesfalls schon vor der Eingabe als ungültig markiert werden, sondern erst dann wenn der User das Feld verlässt (wenn das Feld den Fokus verliert) oder wenn er das Formular abschickt.
<!-- this field is invalid -->
<input type="email" aria-required="true" aria-invalid="true">
Wenn das Feld nicht länger ungültig ist, sollte das Attribut komplett entfernt werden und nicht auf aria-invalid="false" gesetzt. Das Attribut kann auch als Styling-Hook verwendet werden:
/* style invalid fields */
input[aria-invalid="true"] {
border: 2px solid red;
}
Wenn das HTML-Attribut required verwendet wird, sollte darauf geachtet werden, dass die Felder in allen Browsern konsistent vorgelesen werden:
<!-- field is required but not invalid yet; prevent screen
readers from announcing it as invalid by default -->
<input type="text" required aria-invalid="false">
<!-- field is required an invalid -->
<input type="text" required aria-invalid="true">
Wenn ein Feld ungültig ist, wird es meistens rot markiert. Personen mit Farbsehschwäche können aber aufgrund der Farbe alleine nicht herauslesen, dass die Eingabe ungültig war, siehe auch SC 1.4.1 Use of Color. Ein Icon kann helfen, fehlerhafte Felder zu identifizieren.
Fehlermeldungen für ungültige Felder
Die Felder sollten mit inline error messages ausgestattet werden, um dem User zu kommunizieren, was falsch ist und wie er es korrigeren kann. Das erfüllt SC 3.3.3 Error Suggestion.
Relevante Success Criteria
- SC 3.3.3 Error Suggestion (Level AA)
- If an input error is automatically detected and suggestions for correction are known, then the suggestions are provided to the user, unless it would jeopardize the security or purpose of the content.
<!-- associate an error message programmatically with its respective field -->
<input type="email"
aria-required="true"
aria-invalid="true">
aria-describedby="email_error">
<p id="email_error">Please provide an email address.</p>
Statt aria-describedby könnte auch aria-errormessage verwendet werden. Der Unterschied ist, dass damit zwingend aria-invalid verwendet werden muss und dass die Fehlermeldung nur dann vorgelesen werden soll, wenn aria-invalid="true". Anderenfalls muss die Fehlermeldung vor allen Benutzern versteckt werden. Der Support für aria-errormessage ist derzeit noch inkonsistent. Adrian Roselli hat getestet (Link unten).
Fehlermeldungen visuell kommunizieren: Farbe rot, zusätzlicher Text, inline SVG-Icon mit fill="currentColor", damit die Farbe des Icons automatisch angepasst wird. Ein weiterer Vorteil ist, dass die Farbe des Icons im Forced Color Mode erhalten bleibt.
Das SVG sollte auch einen accName haben, damit der gleiche Verwendungszweck auch für Screenreader kommuniziert wird, z.B. mit dem aria-label-Attribut. Alternativ kann das gesamte Icon auch vor dem Screenreader versteckt werden und eine Text-Fehlermeldung für Screenreader alleine verwendet werden.