Code examples

Adding hint/help text

<label for="best-nato-letter">
  The best NATO letter is:
<input type="text" 

<div class="hint" id="best-nato-letter-hint">
  Example: Alpha, Bravo, Charlie
Example: Alpha, Bravo, Charlie

Adding an error

Note: The alert must be structured as below to function properly in VoiceOver, with the alert text nested inside the role="alert" element.

<label for="favorite-nato-letter">
  What is your favorite NATO letter?

<input type="text"
       aria-describedby="favorite-nato-error favorite-nato-hint"

<div role="alert" 
     class="alert inert">
  <!--- Do not reference this alert element
        directly with aria-describedby -->
  <div id="favorite-nato-error">
    <!--- Use JS to inject the alert here -->

<div class="hint" id="favorite-nato-hint">
  Example: Alpha, Bravo, Charlie

<button id="show-error">
  Toggle error
Example: Alpha, Bravo, Charlie

Developer notes

Browser + screenreader quirks

  • Screenreaders do not implement alerts uniformly and must be tested
    • Just because an alert pattern works in one screenreader doesn’t mean it will work in all three
  • The element referenced by the aria-describedby attribute cannot use the role="alert" attribute (see example above for workaround).
  • NVDA will read the alert twice if it appears while the input is in focus: once from the role="alert" being injected and from the aria-describedby association.
  • NVDA needs a fraction of a second to catch up with changes in the DOM, use a setTimeout to delay displaying the alert


  • Inner text describes the hint


  • May have role="alert" if serving as an input error message


  • Use aria-describedby="hint-id" to associate an input with a hint.


  • Hints must not receive focus