Skip to content

Find what you need, instantly

Search components, ARIA roles & attributes, and WCAG criteria.

Forms & Controls

Form patterns

Labels, required fields, inline error handling, error summary, aria-describedby, and autocomplete attributes.

Last verified against WCAG 2.2 and WAI-ARIA APG 1.2 on 2026-07-02.

Implementation

Field-level aria-invalid/aria-describedby, a focus-managed error summary, and non-color error signaling.

forms-pattern.tsx
function handleSubmit(e) {
  e.preventDefault();
  const nextErrors = validate(values);
  setErrors(nextErrors);
  setSubmitted(true);
  if (Object.keys(nextErrors).length > 0) {
    // Move focus into the summary so SR users hear it immediately.
    requestAnimationFrame(() => summaryRef.current?.focus());
  }
}

<div ref={summaryRef} tabIndex={-1} role="alert">
  <p>There are 2 problems with your submission</p>
  <ul>
    <li><button onClick={() => focusField("name")}>Enter your full name.</button></li>
    <li><button onClick={() => focusField("email")}>Enter a valid email address.</button></li>
  </ul>
</div>

<input
  id="email"
  aria-invalid={submitted && !!errors.email}
  aria-describedby={submitted && errors.email ? "email-error" : undefined}
/>
{submitted && errors.email && <p id="email-error">Error: {errors.email}</p>}

Live demo

Fields marked (required) are required.

Required roles, states & properties

Required roles, states, and properties
ElementAttributeWhy
Every input<label htmlFor> associated by idThe only reliable way to give an input a persistent accessible name — placeholder text disappears on input and isn't treated as a label by many screen readers.
Required inputsrequired + aria-required="true"Communicates required state to both native HTML validation and assistive tech; paired with visible, non-color-only text explaining what the asterisk means.
Invalid inputsaria-invalid="true"Marks the field as currently in an error state, announced as "invalid" when the field receives focus.
Invalid inputsaria-describedby → error message idLinks the field to its specific error text so the message is announced right after the field's name and invalid state.
Error summary containerrole="alert" + tabIndex={-1}role="alert" announces the summary as soon as it appears; tabIndex={-1} makes it programmatically focusable via ref (without adding it to the normal tab order) so focus can be moved there on failed submit.
Common fieldsautocomplete="name" | "email" | "tel"Identifies input purpose (SC 1.3.5) so browsers/password managers autofill correctly and AT can convey the expected kind of data.

Keyboard interaction model

Keyboard interaction model
KeyBehavior
Tab / Shift+TabMoves between labeled fields and the submit button in reading order.
Enter (in a text field)Submits the form, triggering validation.
Any key (after failed submit, focus in summary)Tab from the error summary moves to the first listed error link/button; activating it (Enter/Space) moves focus directly to the corresponding invalid field.

Focus management rules

  • On a failed submit, focus moves programmatically (via ref, not just visually) to the error summary.
  • The error summary is focusable (tabIndex={-1}) but not part of the normal tab order, so it doesn't add an extra unexpected stop on a successful pass through the form.
  • Activating an error summary link moves focus directly to the corresponding invalid field, never to an unrelated element.
  • Focus is never moved automatically except in direct response to a user action (submit) — receiving focus on a field never itself triggers validation or a context change (SC 3.2.1/3.2.2).

WCAG 2.2 success criteria mapping

WCAG 2.2 success criteria that apply to this component
SCNameLevelWhy it applies
1.3.5Identify Input PurposeAAForm fields collecting common user info use correct autocomplete attributes.
3.3.1Error IdentificationAInput errors are identified and described to the user in text.
3.3.2Labels or InstructionsALabels or instructions are provided when content requires user input.
3.3.3Error SuggestionAAIf an input error is detected and suggestions are known, they are provided to the user.
3.3.7Redundant EntryAInformation previously entered is auto-populated or available for the user to select.
4.1.2Name, Role, ValueAFor all UI components, name, role, and value are programmatically determinable; states and changes are announced.

References