Blog

Accessible React Forms: Labels, Errors, Helper Text, and aria-describedby

Build accessible React forms with clear labels, helper text, validation errors, and aria-describedby relationships.

ReactAccessibilityFormsUI Components

Accessible React forms need clear relationships between controls and the text that explains them. A text input, label, helper message, and validation error should not be separate visual pieces with no semantic connection.

This is where labels and aria-describedby matter.

Start with a visible label

A form control should have an accessible name. In most cases, that should be a visible label.

Visible labels help everyone:

  • Screen reader users hear what the field is.
  • Voice control users can reference the label.
  • Sighted users can scan the form quickly.
  • The field remains understandable after text is entered.

Placeholders are not a replacement for labels. Placeholder text disappears and often has lower contrast. It is better used for examples, not field names.

Connect labels correctly

In React, a label can be connected to an input with htmlFor and id.

That relationship lets users click the label to focus the field, and it gives assistive technology a reliable name for the input.

For reusable form components, generate stable IDs when the consumer does not provide one, but still allow explicit IDs for advanced composition.

Use helper text for guidance

Helper text explains how to complete a field. It might describe formatting, requirements, or the reason the information is needed.

Examples:

  • "Use at least 8 characters."
  • "We will send confirmation to this address."
  • "Choose the closest match."

Helper text should be visually close to the field and programmatically connected when it affects how the field should be understood.

Use aria-describedby

aria-describedby connects a form control to supporting text. A screen reader can announce the label and then the description.

This is useful for helper text and errors.

If a field has helper text and an error message, the input can reference both IDs:

<input
  id="email"
  aria-describedby="email-helper email-error"
  aria-invalid="true"
/>

The exact implementation can vary, but the principle is the same: supporting text should not be only visual.

Announce validation errors

Validation errors should be clear, specific, and connected to the field.

Avoid vague messages like "Invalid input." Instead, write the action the user can take:

  • "Enter an email address."
  • "Password must include at least 8 characters."
  • "Choose a start date before the end date."

Set aria-invalid when a field has an error, and connect the error message with aria-describedby.

Keep form state visible

Accessible forms need visible states:

  • Required.
  • Optional.
  • Focused.
  • Disabled.
  • Invalid.
  • Loading.
  • Success.

These states should be consistent across the component library. If every form control handles error text differently, users have to relearn the interface on every screen.

Build it into your components

Reusable React form components should make accessible patterns easy:

  • A label prop.
  • A helperText prop.
  • An errorMessage prop.
  • Automatic aria-describedby wiring.
  • Automatic aria-invalid when errors exist.
  • Clear styling for focus and error states.

Boreal UI is built around this kind of component API. The goal is to give product teams accessible defaults while keeping forms themeable and flexible.

Accessible React forms are not complicated because the rules are obscure. They are complicated because teams need to apply the same rules consistently. A good component library helps make that consistency automatic.