Accessible Forms

Forms need to be accessible to both screen readers and keyboard-only users.

Screen reader users typically navigate through a form using the Tab key to jump from form control to form control. Associated form labels are read for each form control when the user navigates to them. Any non-label text content between the form controls is usually skipped over. Be sure to include important cues or instructions in associated labels or at the beginning of the form.

Associate Labels Explicitly with Their Form Controls

The <label> element is used to associate a text label to a form control. This allows a screen reader to read the associated label text when the user navigates to the form control.

  • All form controls need to include an “id” that associates the form control with the respective form label. 

  • The “id” attribute needs to match the “for” attribute in the form label.


1 2 3 <label for=”name” class="control-label">Name</label> <input placeholder="" id="name" formtype="c02" name="name" type="text">


Group Lists of Form Controls When There are Multiple Options to Select From

  • Group the list of options with a “fieldset” 

  • Use a “legend” to describe the list of form control options.

  • Use checkboxes instead of radio buttons when more than one option can be selected

  • User should be able to select text labels

Please see example below.

1 2 3 4 5 6 7 8 9 10 11 <fieldset> <legend>Name</legend> <input id=”equityapplicant” type="checkbox" name="authorization" value="equityapplicant"> <label for="equityapplicant"> I am an Equity Applicant </label><br/> <input id=”equityincubator” type="checkbox" name="authorization" value="equityincubator"> <label for="equityincubator"> My business is an Equity Incubator</label><br/> <input id=”signedaffidavit” type="checkbox" name="authorization" value="signedaffidavit"> <label for=”signedaffidavit”> I registered my business with the Office of Cannabis and have signed an affidavit</label><br/> <input id=”temporarypermit” type="checkbox" name="authorization" value=”temporarypermit”> <label for=”temporarypermit”>I have a temporary cannabis permit</label><br/> </fieldset>

Add a Title Attribute to Form Controls with No Labels

The preferred way is to include a form label with each form controls. However, if this is not possible use the title attribute to label form controls when the visual design cannot accommodate the label (for example, if there is no text on the screen that can be identified as a label) or where it might be confusing to display a label. User agents, including assistive technology, can speak the title attribute.

1 <input class="form-control" title=”Search Regulations” placeholder="Search regulations" name="q" type="text">

Add Required Information to Form Controls

Include the word ‘required’ in the form element to indicate mandatory form fields for screen reader users. 


1 2 3 <label for="fname">Family Name *:</label>  <input type="text" name="familyname" id="fname"   aria-required="true" required>

Accessible Autocomplete Forms

Screen-reader Interactions

  • When the form field gains focus: 

    •  Tell screen reader users that the input field is an auto-suggest.

    •  Tell screen reader users they can select from the suggestion list or type their own input.

    • Tell screen reader users the number of suggestions that are available

  • Allow screen reader users to scroll through the list of suggestions by using the arrow keys.

  • When suggestions are arrowed through they are spoken aloud.

Add ARIA Labels for Screen Reader Users

Add role=”combobox” to the <input> field to tell screen reader users that the input field is an auto-suggest.

  • Default text is “Edit Combo”

Add aria-autocomplete=”both” to the <input> field to tell screen reader users they can select from the suggestion list or type their own input. 

  • This is the default text: “To set the value use the arrow keys or type the value”

  • You can customize this text by using the aria-describedby="initInstr"

  • Screen reader users can’t use the arrow keys until the autocomplete starts. 

  • You may want to use a more customized message such as “When autocomplete results are available use up and down arrows to review and enter to select.”

Add aria-live=”assertive” to announce the number of results available. The content of the <div>, which isn’t visible on screen, updates every time the list length changes.

Add aria-owns to the <input> field to link the suggestion list to the input field.

Add role=“listbox“ to the suggestion list <div> to tell screen reader users it contains a list of selectable items.

Add aria-activedescendant to the <input> element and populate it with the id of the currently highlighted list item. The aria-activedescendant value changes as the user presses the Up and Down arrows.

Add role=“option“ to each suggestion item, along with a unique id. That id is used by the aria-activedescendant attribute of the <input> element, whose value changes as users move through the list items with the arrow keys.

Add aria-expanded=”true” to indicate that the popup list is displayed.

Code Example

Here is an example of what the code would look like

1 2 3 4 5 6 7 8 9 10 <form action=""> <div data-widget="accessible-autocomplete"> <label for="name">Name:</label> <input type="text" id="name" class="autocomplete-search-field" aria-describedby="initInstr" aria-owns="results" role=”combobox” aria-expanded=”true” aria-autocomplete="both" aria-activedescendant="suggestion-1"> <div id=”results” class="autocomplete-list" role=”listbox”> <div class=”autocomplete-suggestion” id=”suggestion-1” role=”option”> Christina Lutz</div> </div> <span id="initInstr" style="display: none;">When autocomplete results are available use up and down arrows to review and enter to select.</span> <div aria-live="assertive" class="screen-reader-text">Two suggestions found, use up and down arrows to review</div> </div></form>

Declaring Form Controls as Invalid

Wait to declare form controls as invalid until the form control has lost focus, or there has been an adequate delay in key presses (maybe a few seconds).

Example Default State:

<form novalidate>

<label for="name"> Name:</label>

<input id="name" required aria-invalid="false">


Example Invalid Error Message State:

<form novalidate>

<label for="name">  Name:</label>

<input id="name" required aria-describedby="name_msg" aria-invalid="true">

<span id="name_msg">Please enter your name.</span>


Code Example:

Error and Alert Messaging Within Forms

Please see Alert and Error Message Guidelines in connection with forms.