UX and accessibility

Form validation: build accessible error messages

Web designer tests a contact form with a keyboard beside a smartphone.

You click Send and the form stays where it is. A red border appears around the email field. Is it empty, malformed or rejected by the server? To a developer, validation may be a boolean. To the visitor, it is the moment their entire task can stall.

An accessible error does more than mark a value invalid. It identifies the problem, connects it to the right control and makes recovery possible. That requires clear writing as well as sound HTML and thoughtful focus management.

Start with the message, not the JavaScript

“Invalid input” may describe the software state but tells the visitor little. For an empty field, say “Enter your email address.” For an incorrect format, explain what to change and provide an example. WCAG 2.2 criteria 3.3.1 and 3.3.3 address text identification of errors and correction suggestions when appropriate. A coloured border alone is not enough; this example is not a claim that the whole form conforms to WCAG.

Give the field a name and connect the error

Use a persistent visible label, an input with native constraints and an error element linked by aria-describedby. The example below contains one field so the relationship is easy to inspect.

<form id="contact" novalidate>
  <label for="email">Email address (required)</label>
  <input id="email" name="email" type="email"
         required aria-describedby="email-error">
  <p id="email-error"></p>
  <button type="submit">Send</button>
</form>

The required attribute sets the requirement and type=email enables native format checks. The novalidate attribute turns off interactive browser validation on submission; use it only when your replacement handles errors accessibly.

Let the browser do its part

The Constraint Validation API distinguishes a missing required value (valueMissing) from a malformed email address (typeMismatch). You do not need to invent a regular expression for every standard field.

const form = document.querySelector('#contact');
const email = document.querySelector('#email');
const error = document.querySelector('#email-error');

function validateEmail() {
  const message = email.validity.valueMissing
    ? 'Enter your email address.'
    : email.validity.typeMismatch
      ? 'Enter a valid email address, for example name@company.com.'
      : '';
  error.textContent = message;
  if (message) email.setAttribute('aria-invalid', 'true');
  else email.removeAttribute('aria-invalid');
  return message === '';
}

form.addEventListener('submit', (event) => {
  event.preventDefault();
  if (!validateEmail()) {
    email.focus();
    return;
  }
  // Example ends here: implement server-side processing.
});
email.addEventListener('input', () => {
  if (email.getAttribute('aria-invalid') === 'true') validateEmail();
});

This code illustrates validation, but does not send any data. Its API usage has been checked against the documentation; it has not been tested as a complete form across browsers or screen readers. Passing client-side checks does not mean a server has received a submission.

When should an error appear?

Showing an error after every keystroke can punish someone who has only just begun typing. Here, errors appear on submission and are updated while an already-invalid field is corrected. It is one reasonable interaction pattern, not a universal prescription. A larger form may also benefit from a linked error summary and carefully designed announcements for assistive technology.

The browser is not a security boundary

Client-side checks can be bypassed. Validate requirements and allowed values on the server too. If server processing fails, preserve other valid inputs and explain the problem. Only display success once the server has accepted the submission. W3C guidance distinguishes feedback beside individual fields from feedback about the whole form.

Test whether the visitor can recover

Submit an empty form, then enter an invalid address and correct it. Check whether the error clears and focus remains understandable. Repeat with a keyboard, zoom, a narrow viewport and a screen reader; simulate a server failure. Record the device, browser and assistive technology used. An automated scan or short code example cannot establish full accessibility.

For the broader contact journey, read seven checks for an accessible contact form. Our sponsor explains BlazeForce Forms and submission handling; assess any plugin against these principles.

The test is whether the task can be completed

Validation is technically about whether input satisfies rules. For the visitor, the important question is whether they can understand the error and finish the task. Make that whole journey part of your acceptance criteria, rather than treating a red border as completion.

Sources

Contact us

Tell us how we can help; we will respond within two working days.

Only needed when you want us to call you back.
For sponsorship, include your company name and proposal. For a correction, include the page URL.

We only use your details to handle this request.

Share this article

Share this article