Input forms are a vital way to interact with users; making them accessible to all users is critical. HTML has many out-of-the-box elements, tags and techniques — outlined and illustrated below — to provide these capabilities.

Groups

HTML fieldset and legend tags

When to use the HTML fieldset and legend tags:

DO USE fieldset and legend

  • On a single multiple choice question with radio buttons or checkboxes
  • On several questions relating to the same topic

DO NOT USE fieldset and legend

On a single form field that asks for a single piece of information

Required fields

Use aria-required="true" instead of the HTML required attribute since the latter is not implemented uniformly across browsers and tends to announce empty required fields as invalid when the user first focuses on the field.

If you have to use the HTML required attribute, use it in conjunction with aria-invalid to avoid user confusion.

Code Example 1

<label for="name">
    Name
</label>
<input id="name" type="text" aria-required="true">

Code Example 2

<label for="name">
    Name
</label>
<input id="name" type="text" required aria-invalid="false">

Form Inputs

All form inputs must be labelled, so make sure the label tag gets the for attribute. This ensures the label will get announced when the screen reader user focuses on the field.

Code Example

<label for="name">
    Name
</label>
<input id="name" type="text">

Error messages

Invalid fields need visual and non-visual cues to communicate. Use “live regions” so that screen readers will announce the error message:

On page load

  • aria-describedby on input pointing to the related error message container
  • Error message container gets role="alert" and aria-live="polite"

On error

  • aria-invalid="true" on the input for non-visual
  • Inject the error message text into the error container

Hint text

Hint text should be programmatically associated with its related input so that it gets announced by screen readers when a user focuses on the field. This is done by attaching aria-describedby to the related input and pointing it to the id of the hint text container.

Example

An error message and hint text will display upon submitting the following form if the requirements aren't met. In this case the requirements are that the field cannot be left blank. The error message and hint text will both be visually rendered and also read by a screen reader if one is in use.

Full first name required.

Implementation

Without an error

<form>
    <label for="name">
        Name
    </label>
    <input type="text" aria-describedby="name-error hint-text-name" id="name" aria-required="true" />
        <p id="hint-text-name">
            Enter your full first name and not a nickname.
        </p>
    <div id="name-error" aria-live="polite" role="alert"></div>
    <button type="submit">Submit</button>
</form>

With an error

<form>
    <label for="name">
        Name
    </label>
    <input type="text" aria-invalid="true" aria-describedby="name-error hint-text-name" id="name" aria-required="true" />
    <p id="hint-text-name">
        Enter your full first name and not a nickname.
    </p>
    <div id="name-error" aria-live="polite" role="alert">
        A name is required.    
    </div>
    <button type="submit">Submit</button>
</form>

Note: aria-describedby can take multiple space delimited ID references, so you can associate both hint and error elements to one field.

More Resources