Form

Errors

Published on

Description anchor

Form errors communicate validation failures to users. Errors should be associated with their fields programmatically and announced to screen readers via live regions.

Avoid relying on browser default validation — it has significant accessibility and usability gaps.

Example anchor

Open in new tab (opens in new tab)
View HTML markup
  <div role="alert" class="form-errors">
  <h2>Errors</h2>
  <ul>
    <li><a href="#text-err">text error message </a></li>
    <li><a href="#textarea-err">textarea error message </a></li>
    <li><a href="#select-err">select error message </a></li>
    <li><a href="#checkbox-err">checkbox error message </a></li>
    <li><a href="#radio-err">radio error message </a></li>
    <li><a href="#file-err">file error message </a></li>
  </ul>
</div>
<form method="POST" novalidate="">
  <div><label for="text-err">Text</label> <span id="text-err-error" aria-live="polite">text error message</span> <input value="" id="text-err" name="text-err" dir="auto" autocapitalize="off" autocomplete="off" autocorrect="off" spellcheck="false" type="text" aria-describedby="text-err-error" aria-invalid="true" /> </div>
  <div><label for="textarea-err">Textarea</label> <span id="textarea-err-error" aria-live="polite">textarea error message</span> <textarea id="textarea-err" dir="auto" name="textarea-err" aria-describedby="textarea-err-error" aria-invalid="true"></textarea></div>
  <div><label for="select-err">Select</label> <span id="select-err-error" aria-live="polite">select error message</span>
    <div><select id="select-err" name="select-err" aria-describedby="select-err-error" aria-invalid="true">
        <option label="A" value="a"></option>
        <option label="B" value="b"></option>
      </select></div>
  </div>
  <fieldset name="checkbox-err">
    <legend id="checkbox-err">Checkboxes</legend> <span id="checkbox-err-error" aria-live="polite">checkbox error message</span>
    <div><input value="a" id="checkbox-err-a" name="checkbox-err" type="checkbox" checked="" aria-describedby="checkbox-err-a-hint" /> <label for="checkbox-err-a">A</label> </div>
    <div><input value="b" id="checkbox-err-b" name="checkbox-err" type="checkbox" aria-describedby="checkbox-err-b-hint" /> <label for="checkbox-err-b">B</label> </div>
  </fieldset>
  <fieldset name="radio-err">
    <legend id="radio-err">Radios</legend> <span id="radio-err-error" aria-live="polite">radio error message</span>
    <div><input value="a" id="radio-err-a" name="radio-err" type="radio" checked="" aria-describedby="radio-err-a-hint" /> <label for="radio-err-a">A</label> </div>
    <div><input value="b" id="radio-err-b" name="radio-err" type="radio" aria-describedby="radio-err-b-hint" /> <label for="radio-err-b">B</label> </div>
  </fieldset>
  <div><label for="file-err">File</label> <span id="file-err-error" aria-live="polite">file error message</span> <input id="file-err" name="file-err" is="ds-input-file" type="file" aria-describedby="file-err-error" aria-invalid="true" /> </div> <button type="button">Submit</button>
</form>

Accessibility anchor

  • Use aria-describedby linking fields to their error messages. It has more reliable cross-platform support than aria-errormessage.
  • Set aria-invalid="true" only after a validation attempt — never on initial page load.
  • Error messages should use aria-live="polite" (not assertive) to preserve field name announcements.
  • Error IDs follow the pattern {id}-error. Hint IDs follow {id}-hint. Build aria-describedby from both.
  • Avoid default browser validation — error messages disappear, don't scale with zoom, and lack context. Use novalidate on forms.

References anchor

  • Alert — for page-level error summaries

Variables anchor

None for form errors