Accessible form validation without a framework
// Editorial team
Most contact and submission forms need only a few rules: a required field, a minimum length, a valid URL. The browser already knows how to check all of them. The work is in reporting errors in a way everyone can follow.
Start with native constraints
Put the rules in the markup: required, type="url", minlength, pattern. That gives you input.validity for free, and the form still has sensible rules if your script fails to load. Add novalidate to the form only once your script is running, so the browser's own bubbles do not appear on top of yours.
form.noValidate = true;
form.addEventListener('submit', e => {
const bad = [...form.elements].filter(el => el.willValidate && !el.checkValidity());
bad.forEach(showError);
if (bad.length) { e.preventDefault(); bad[0].focus(); }
});
Error text that screen readers hear
Give every field an empty element for its message, linked with aria-describedby. When the field fails, write the message into that element and set aria-invalid="true" on the field. When focus moves to the field, a screen reader reads the label, then the description, so the user hears what went wrong.
<label for="f-msg">Message</label>
<textarea id="f-msg" required minlength="20" aria-describedby="f-msg-err"></textarea>
<span class="err" id="f-msg-err"></span>
Write messages in plain words: "Please write at least 20 characters" rather than "Invalid input". Avoid relying on a red border alone. Around one in twelve men has some form of colour vision deficiency, and red borders are often missed.
When to validate
Checking on every keystroke makes people feel shouted at before they have finished typing. A pattern that works well:
- Validate the whole form on submit.
- After a field has shown an error once, re-check it on
inputso the message disappears as soon as it is fixed. - Do not validate a field on
blurif the user has not typed anything yet.
Focus the first error
Moving focus to the first invalid field is the most useful single thing you can do. Keyboard and screen reader users land exactly where the problem is, and sighted users see the page scroll to it. If the form is long, a short summary at the top listing the errors as links also helps.
Do not stop there
Client-side checks are for the user's convenience. Anything that reaches a server still has to be validated there, because a request can be sent without your page at all. We cover the server side in our website build work.