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

Screen reader users and keyboard only users typically navigate through a form using the TAB key, on the keyboard, to jump from form control to form control.

Forms Checklist and Overview

Please see our in-depth forms guide for accessible markup and acceptance criteria.

Accessible Form Elements, Acceptance Criteria and Markup

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.

Example:

<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

Please see example below.

<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.

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

Notify Screen Reader Users When Form Elements Are Required to Complete

Include the word ‘required’ or aria-required=”true' in the form element to indicate mandatory form fields for screen reader users. 

Providing HTML5 Required Attribute

If this attribute is used on any form field, it is identified as required by assistive technologies.

Example: 

<label for="fname">Family Name *:</label>
 <input type="text" name="familyname" id="fname" 
required>

Providing Aria-Required Attribute

Similar to the “required” attribute in HTML5, WAI-ARIA introduced the “aria-required” attribute. If this attribute is used on a form control it will be exposed as required by assistive technologies.

No validation or "enforcement" mechanism comes along with this attribute, and it has no visual impact.

Example: 

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

Let Screen Reader Users Know When Radio Button Form Controls are Mandatory/Required to Complete

Add the aria-required attribute in combination with the radiogroup role in the fieldset tag.

This works with a group of radio buttons, but not with a group of checkboxes.

Example: 

<fieldset aria-required="true" role="radiogroup">  
    <legend class="field-required">
      What will you be selling?
    </legend>  
         <span class="flex-shrink-0">
        <input id="eqobtmq-merchandise" value="merchandise" lang="en" type="radio" name="data[whatWillYouBeSelling][e26kiyb-eqobtmq]" class="input-radio position-relative d-block mr-2 mb-0" ref="input" aria-invalid="false">
      </span>
 <label for="eqobtmq-merchandise" class="d-flex flex-items-center fs-inherit my-2">
      <span class="flex-auto">
        Merchandise
      </span>
    </label>      
      <span class="flex-shrink-0">
        <input id="eqobtmq-prepackagedFoodOrDrink" value="prepackagedFoodOrDrink" lang="en" type="radio" name="data[whatWillYouBeSelling][e26kiyb-eqobtmq]" class="input-radio position-relative d-block mr-2 mb-0" ref="input" aria-invalid="false">
      </span>
<label for="eqobtmq-prepackagedFoodOrDrink" class="d-flex flex-items-center fs-inherit my-2">
      <span class="flex-auto">
        Prepackaged food or drink
      </span>
    </label>      
      <span class="flex-shrink-0">
        <input id="eqobtmq-both" value="both" lang="en" type="radio" name="data[whatWillYouBeSelling][e26kiyb-eqobtmq]" class="input-radio position-relative d-block mr-2 mb-0" ref="input" aria-invalid="false">
      </span>
<label for="eqobtmq-both" class="d-flex flex-items-center fs-inherit my-2">
      <span class="flex-auto">
        Both merchandise and prepackaged food or drink
      </span>
    </label>  
</fieldset>

Let Screen Reader Users Know When a Group of Checkboxes are Mandatory/Required to Complete

Add an invisible required label that will be announced by the screen reader. A sighted user will not see this text.

Example:

 <fieldset>
 <legend class="field-required">
      Type of addenda <span class="visuallyhidden">required</span>
  </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> 

Let Screen Reader Users Know When Standalone/Single Checkboxes are Mandatory/Required

You can make standalone/single checkboxes required by using the aria-required="true" and required attributes.

Then add the role=”checkbox” to the single checkbox.

Example:

<input value="0" lang="en" type="checkbox" name="data[sellingLegally]" ref="input" role="checkbox" required class="input-checkbox position-relative d-block mr-2 mb-0" aria-invalid="false" checked="true">

<input value="0" lang="en" type="checkbox" name="data[proofOfOwnership]" ref="input" role="checkbox" required class="input-checkbox position-relative d-block mr-2 mb-0" aria-invalid="false" checked="true">

<input value="0" lang="en" type="checkbox" name="data[allInformationIsTrue]" ref="input" role="checkbox" required class="input-checkbox position-relative d-block mr-2 mb-0" aria-invalid="false" checked="true">

Place Important Form Instructions and Text in a Logical Reading Order for Screen Reader Users and Associate Them with Specific Fields Using ARIA

If you place the form instructions above the form control screen reader users will be provided with critical information before the form control receives keyboard focus.

Also, screen reader users sometimes navigate forms using the Tab key to jump from form control to form control in which case they would skip the form instructions. 

To cover this scenario you can use the “aria-describedby” attribute to associate the form instructions with the form control.

Example:

<label for="input-es2f54a" class="field-required">
Your name
</label>
<div class="fg-light-slate mt-1" id=”yournamenote”>
You must be the business owner or the authorized representative of a nonprofit.
</div>
<div ref="element">
<div class="form-input">
  <input value="Bob Smith" spellcheck="true" lang="en" class="form-control" type="text" aria-describedby=”yournamenote” name="data[name]" aria-required="true" required="" id="input-es2f54a" ref="input" aria-invalid="false">
</div>
</div>  

Accessible Autocomplete Forms

Screen-reader Interactions


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

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. 

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

<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" class="visuallyhidden">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>

https://codepen.io/ademcifcioglu/pen/xdOyXv

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">

</form>

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>

</form>

Code Example: https://codepen.io/TPG/pen/3b68c22db120c0960503fe892bb2c068

Error and Alert Messaging Within Forms

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

As a Keyboard Only User I Should be Able to Interact with a Calendar Widget

As a keyboard only user I should be able to use the tab key to access the calendar widget as well as navigate through the months and years.

I should also be able to use the arrow keys to navigate between dates. 

Here is an example of a fully accessible calendar widget. 

See Code Example Here:

https://www.w3.org/TR/wai-aria-practices/examples/dialog-modal/datepicker-dialog.html  

As a Keyboard Only and Screen Reader User I Should be Able to Delete Selected Items within a Multiselect Combobox Dropdown Menu

As a keyboard only and screen reader user,  I should be able to use the shift+tab keys to tab backwards to a button/label and then press the spacebar (or enter key) to remove/delete that item.

Here I’m referring to the buttons that appear once you have made a selection.

Within this article https://www.24a11y.com/2019/select-your-poison-part-2/

there is a codepen multiselect combobox example that places the selected buttons above the form control.

This example allows me to use the shift+tab keys to navigate back to all buttons and use the spacebar or enter key to delete them, not just the last button. 

In this example the screen reader will also make an announcement to press the spacebar to delete an item. 

Avoid Using Dashes in Placholder Tags in Form Controls

As a screen reader user I should NOT be provided with dashes in a placeholder tag to enter for example a phone number.

For example when entering phone number.

When the form control receives keyboard focus the screen reader will announce the dashes as follows “underline underline underline underline underline underline type of text”.

Incorrect Way:

<input value="" spellcheck="true" inputmode="decimal" lang="en" class="form-control" type="text" name="data[phoneNumber]" required="" id="input-ebt1nqd" ref="input" placeholder="___-___-____" aria-invalid="false">

Correct Way:

<input value="" spellcheck="true" inputmode="decimal" lang="en" class="form-control" type="text" name="data[phoneNumber]" required="" id="input-ebt1nqd" ref="input" aria-invalid="false">