Validation is only useful if everyone can understand it. People who use screen readers or only the keyboard need the same information that sighted mouse users get from a red border.
A checklist
- Every field has a visible
<label>, connected withforandid. - Error messages are real text, near the field. Do not rely on color alone.
- Link the message to the field with
aria-describedby, so screen readers read it with the field. - Mark the field invalid with
aria-invalid="true". - Announce errors: a summary with
role="alert", oraria-live, so they are spoken when they appear. - Move focus to the first invalid field (or the summary) after a failed submit.
- Say how to fix it, not only what is wrong.
- Mark required fields in text too (for example “required”), not only with a star colour.
Putting it together
<style>
.field { margin-bottom: 10px; }
.error { color: #b00020; font-size: 14px; margin: 2px 0 0; }
input[aria-invalid="true"] { border: 2px solid #b00020; }
</style>
<form id="f" novalidate>
<div role="alert" id="summary" tabindex="-1"></div>
<div class="field">
<label for="email">Email (required)</label><br>
<input id="email" type="email" aria-describedby="email-help email-error" required>
<div id="email-help" style="font-size:13px;color:#555">We only use it to send your receipt.</div>
<div id="email-error" class="error"></div>
</div>
<button>Send</button>
</form>
<script>
const form = document.querySelector("#f");
const email = document.querySelector("#email");
const error = document.querySelector("#email-error");
const summary = document.querySelector("#summary");
form.addEventListener("submit", event => {
event.preventDefault();
const bad = !email.validity.valid;
email.setAttribute("aria-invalid", String(bad));
error.textContent = bad ? "Enter an email address like name@example.com." : "";
summary.textContent = bad ? "There is 1 problem with the form." : "";
if (bad) email.focus();
});
</script>
Why each piece matters
aria-describedbymakes a screen reader read the help text and the error after the field name.aria-invalid="true"tells assistive technology the value is not valid.role="alert"makes the summary spoken as soon as its text changes.- Focusing the first bad field saves a keyboard user from tabbing through the whole form.
Placeholders are not labels
A placeholder disappears when typing and often has low contrast. Use a real label.
Do not move focus on every keystroke
Validating while the user types and jumping around is disorienting. Move focus only after a submit attempt.
Test it
Try your form with the keyboard only (Tab, Shift+Tab, Enter), and with a screen reader if you can. If you cannot complete the form without a mouse, fix that first.
Related reading
aria-live in more depth.