React

Accessible form errors

An accessible form error reaches three channels: visible text, linked attributes and a screen reader announcement. Miss one and someone is locked out.

Key points

  • The error goes in visible text next to the field, not only in a red border.
  • aria-describedby links the message to the field and aria-invalid flags the invalid value.
  • The announcement must be short: one message per submit, not one per field.

An accessible form error reaches three channels: visible text next to the field, attributes linked to the field, and an announcement for screen readers. Miss one channel and someone is locked out.

Three channels, not one

Visible text serves people who look at the screen; aria-describedby ties that text to the field; aria-invalid tells the screen reader the value is wrong. An error signalled by colour alone never reaches someone who cannot tell red from green.

The markup that holds up

Email

{error && (
  
    {error}
  
)}

A field without an error has no aria-describedby: the attribute appears only when a message exists, so the screen reader does not announce an empty id.

The three rules

  • The message is text: an icon with a title does not replace the sentence that explains how to fix the value.
  • Focus stays close: after submit the focus moves to the first invalid field, not to the top of the page.
  • The announcement is short: one message per submit, otherwise the live region reads everything twice.

A check from the command line

npx @axe-core/cli http://localhost:5173 --exit

axe, released under the MPL-2.0 licence, finds missing attributes but cannot judge whether the message makes sense: the screen reader test stays manual.

Live records in the catalogue

Three forms to start from: login-form, registration-stepper and the form blocks category. To browse start from 111,985 components.

The limitation

The link works only when the id exists in the DOM as the error appears; an announcement through role="alert" on a node that was already there is not read by every voice. Inserting the node with the message, as in the snippet, and testing on at least two voices is safer.

Where to continue

The full checklist is in accessible React components; the testing method is in accessibility audit; the measured comparison of libraries is in React UI libraries.

Frequently asked questions

Is a red border enough to signal an error?

No, colour alone reaches neither someone who cannot tell it apart nor a screen reader. You need written text linked to the field.

role alert or aria-live?

role alert is a polite live region with high priority, so it suits an error. On nodes that already exist, insert the node together with the message.

Where does focus go after a failed submit?

To the first invalid field, so keyboard users resume at the right point instead of hunting for the error.

Does an automated test cover form accessibility?

No, it covers missing attributes. Testing with two screen readers and the keyboard is still required.

Should the message sit above or below the field?

Below the field, right after it, is the usual position. What matters is that reading order stays field first, then message.