Checkboxes
- The
<fieldset>
surrounds the entire grouping of checkboxes or radio buttons. The<legend>
provides a description for the grouping. - Some assistive technology reads the legend text for each fieldset, so it should be brief and descriptive. This helps someone using assistive technology to understand the question they are answering with the group of checkboxes.
- WAI-ARIA provides a grouping role that functions similarly to
fieldset
andlegend
. In option #2 thediv
element hasrole=group
to indicate that the contained elements are members of a group and thearia-labelledby
attribute references the id for text that will serve as the label for the group. Note: This method is not supported by all browser/AT devices.
WCAG 2.1 Guidelines
1.1.1 Non-text Content - All non-text content that is presented to the user has a text alternative that serves the equivalent purpose. (Level A)
1.3.1 Info and Relationships - Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text. (Level A)
2.4.6 Headings and Labels - Headings and labels describe topic or purpose. (Level AA)
3.3.2 Labels or Instructions - Labels or instructions are provided when content requires user input. (Level A)
4.1.2 Name, Role, Value - For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies. (Level A)
Option #1: Use fieldsets to group options
Option #2: Use ARIA to group options
Who is the best Beatle?
<section class="checkboxes-section">
<h3>Option #1: Use fieldsets to group options</h3>
<fieldset>
<legend>Who is your favorite 19th century scientist</legend>
<div class="checkbox column">
<input id="bell" type="checkbox" name="scientist" value="bell"/>
<label for="bell">Alexander Graham Bell</label>
<input id="curry" type="checkbox" name="scientist" value="curry"/>
<label for="curry">Marie Curie</label>
<input id="lovelace" type="checkbox" name="scientist" value="lovelace"/>
<label for="lovelace">Ada Lovelace</label>
<input id="nobel" type="checkbox" name="scientist" value="nobel"/>
<label for="nobel">Alfred Nobel</label>
<input id="pasteur" type="checkbox" name="scientist" value="pasteur"/>
<label for="pasteur">Louis Pasteur</label>
<input id="tesla" type="checkbox" name="scientist" value="tesla"/>
<label for="tesla">Nikola Tesla</label>
</div>
</fieldset>
<div class="break"></div>
<h3>Option #2: Use ARIA to group options</h3>
<div role="group" aria-labelledby="beatle_head">
<h4 id="beatle_head" class="bold">Who is the best Beatle?</h4>
<div class="checkbox row">
<input id="beatle_john" type="checkbox" name="beatle" value="beatle_john"/>
<label for="beatle_john">John Lennon</label>
<input id="beatle_paul" type="checkbox" name="beatle" value="beatle_paul"/>
<label for="beatle_paul">Paul McCartney</label>
<input id="beatle_george" type="checkbox" name="beatle" value="beatle_george"/>
<label for="beatle_george">George Harrison</label>
<input id="beatle_ringo" type="checkbox" name="beatle" value="beatle_ringo"/>
<label for="beatle_ringo">Ringo Starr</label>
</div>
</div>
</section>
Copied!
Search
- Wrap search components in a parent element
role="search"
to increase their discoverability to assistive technologies. - Whenever possible, use the
label
element to explicitly associate text with form elements. Thefor
attribute of the label must exactly match theid
of the form control. - Some form fields do not need explicit
label
elements, when next to a button with descriptive text. Ex. search field next to a button labeled search. In these cases you should still have alabel
in the markup, but you can hide it visually. - Note that placeholders are not recognized by all assistive technologies, and thus are not adequate replacements for appropriate labeling. Additionally, assistive technologies that do announce placeholders will read the placeholder first, then the input's label and then type of input. So be sure not to repeat an input's label as its placeholder, otherwise it will be announced multiple times.
WCAG 2.1 Guidelines
1.1.1 Non-text Content - All non-text content that is presented to the user has a text alternative that serves the equivalent purpose. (Level A)
1.3.1 Info and Relationships - Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text. (Level A)
2.4.6 Headings and Labels - Headings and labels describe topic or purpose. (Level AA)
3.3.2 Labels or Instructions - Labels or instructions are provided when content requires user input. (Level A)
4.1.2 Name, Role, Value - For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies. (Level A)
Option #1: Search Input with Visible Label
Option #2: Hide the label element
Option #3: Use aria-label
<section class="search-section">
<h3>Option #1: Search Input with Visible Label</h3>
<div role="search">
<label for="search_1" style="display: block;">Search the site:</label>
<input type="search" name="search" id="search_1" class="search-form__input" />
<button type="submit"><span class="visuallyhidden">Perform</span>Search</button>
</div>
<div class="break"></div>
<h3>Option #2: Hide the label element</h3>
<div role="search">
<label for="search_2" class="visuallyhidden">Search the site</label>
<input type="search" name="search" id="search_2" class="search-form__input" placeholder="search for..." />
<button type="submit"><span class="visuallyhidden">Perform</span>Search</button>
</div>
<div class="break"></div>
<h3>Option #3: Use aria-label</h3>
<div role="search">
<input type="search" name="search" aria-label="Search">
<button type="submit"><span class="visuallyhidden">Perform</span>Search</button>
</div>
</section>
Copied!
Select Lists
- The
<fieldset>
surrounds the entire grouping of checkboxes or radio buttons. The<legend>
provides a description for the grouping. - Some assistive technology reads the legend text for each fieldset, so it should be brief and descriptive. This helps someone using assistive technology to understand the question they are answering with the group of radio buttons.
- For select elements with groups of options, the
optgroup
element can be used to indicate such groups. Thelabel
attribute of theoptgroup
element is used to provide a label for the group. This is especially useful for lists with many related options.
WCAG 2.1 Guidelines
1.1.1 Non-text Content - All non-text content that is presented to the user has a text alternative that serves the equivalent purpose. (Level A)
1.3.1 Info and Relationships - Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text. (Level A)
2.4.6 Headings and Labels - Headings and labels describe topic or purpose. (Level AA)
3.3.2 Labels or Instructions - Labels or instructions are provided when content requires user input. (Level A)
4.1.2 Name, Role, Value - For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies. (Level A)
Option #1: Select with no grouping
Option #2: Select with grouping
<section class="select-section">
<h3>Option #1: Select with no grouping</h3>
<div class="select">
<label for="section1" class="visuallyhidden">Label for section 1</label>
<select id="section1" name="section1">
<option label="First select" disabled selected>First select</option>
<option label="Option 1.1">Option 1.1</option>
<option label="Option 1.2">Option 1.2</option>
</select>
<div class="select__arrow"></div>
</div>
<div class="select">
<label for="section2" class="visuallyhidden">Label for section 2</label>
<select id="section2" name="section2">
<option label="Second select" disabled selected>Second select</option>
<option label="Option 2.1">Option 2.1</option>
<option label="Option 2.2">Option 2.2</option>
</select>
<div class="select__arrow"></div>
</div>
<div class="break"></div>
<h3>Option #2: Select with grouping</h3>
<div class="select">
<label for="lecture" class="visuallyhidden">Choose a Lecture</label>
<select id="lecture" name="lecture">
<option label="Choose a Lecture" disabled selected>Choose a Lecture</option>
<optgroup label="1.0 The History of the World: Part I">
<option label="Lecture 1.1" value="1.1">Lecture 1.1: In the Beginning</option>
<option label="Lecture 1.2" value="1.2">Lecture 1.2: Stuck in the Middle</option>
<option label="Lecture 1.3" value="1.3">Lecture 1.3: At the End</option>
</optgroup>
<optgroup label="2.0 The History of the World: Part II">
<option label="Lecture 2.2" value="2.1">Lecture 2.1: Wait! There's More</option>
</optgroup>
</select>
<div class="select__arrow"></div>
</div>
</section>
Copied!
Text Inputs & Textarea
- Keep it simple - not all browsers correctly expose multiple labels that are linked to the same form element.
- Use labels for every input and make the
for=""
andid=""
values match. IDs must be unique on each page, only one label can be associated to each unique form element. - Make required fields obvious by using an indicator - border color change, asterisk, description text, etc.
- Fields with error validation should have
aria-describedby
to insure that the associated field level error message is read by assistive technology. If the error message has anid="my-error-message"
, then the input should havearia-describedby="my-error-message"
.
WCAG 2.1 Guidelines
1.1.1 Non-text Content - All non-text content that is presented to the user has a text alternative that serves the equivalent purpose. (Level A)
1.3.1 Info and Relationships - Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text. (Level A)
2.4.6 Headings and Labels - Headings and labels describe topic or purpose. (Level AA)
3.3.2 Labels or Instructions - Labels or instructions are provided when content requires user input. (Level A)
4.1.2 Name, Role, Value - For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies. (Level A)
<section class="text-inputs-section">
<form>
<label for="first-name">First Name</label>
<input id="first-name" type="text" name="textfield">
<label for="last-name" class="required-field">Last Name</label>
<input id="last-name" type="text" name="textfield" aria-describedby="required-message" required>
<div id="required-message" class="visuallyhidden">This field is required.</div>
<label for="username">Username</label>
<input id="username" type="text" name="textfield" aria-describedby="username-help-text" aria-invalid="true">
<span id="username-help-text">There was an error with the input above.</span>
<label for="city">City</label>
<input id="city" type="text" name="textfield" aria-describedby="city-help-text" aria-invalid="false">
<span id="city-help-text">The input above is successful.</span>
<label for="address">Enter your street address</label>
<textarea id="address" name="addresstext"></textarea>
<input type="submit" value="Submit">
</form>
</section>
Copied!
Toggles
- When you can, use a
<button>
element and includearia-pressed
orrole="switch"
for your toggles. - You can add optional labels to your toggles, just make sure the label element includes an
id
and the toggle button includes anaria-labelledby
tag that match. - Make sure you include
aria-checked
on toggles, with JavaScript changing the state on click from true to false (or the reverse). - Make sure you check the contrast of the toggle text against the background (if text is used).
Resources
WCAG 2.1 Guidelines
1.1.1 Non-text Content - All non-text content that is presented to the user has a text alternative that serves the equivalent purpose (some exceptions). (Level A)
Note: If non-text content is pure decoration, is used only for visual formatting, or is not presented to users, then it does not need text alternatives.
4.1.2 Name, Role, Value - For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies. (Level A)
<section class="toggles-section">
<div>
<button type="button" data-action="aria-switch" aria-labelledby="toggle_label" aria-checked="false" role="switch">
<span></span>
</button>
<span id="toggle_label" class="optional-label">Optional Label</span>
</div>
<button type="button" data-action="aria-switch" aria-label="Toggle Text" aria-checked="true" role="switch" class="text">
<span></span>
</button>
<button type="button" data-action="aria-switch" aria-label="Toggle Reverse" aria-checked="true" role="switch" class="reverse">
<span></span>
</button>
<button type="button" data-action="aria-switch" aria-label="Toggle Reverse with Text" aria-checked="false" role="switch" class="reverse text">
<span></span>
</button>
<button type="button" data-action="aria-switch" aria-label="Toggle Flip" aria-checked="false" role="switch" class="flip">
<span></span>
</button>
</section>
Copied!
Tooltips
- Tooltips should not receive focus. The focus should remain on the field, button, or link the tooltip is about.
- Tooltips should not be revealed until a short time has passed (~1-5 seconds).
- Depending on the tooltip option you choose, there may be additional ARIA tags you should apply. Add
aria-describedby="example1"
on an input field and link it to a related section with a matching ID selectorid="example1"
. - Whenever possible, use descriptive text on your form fields that does need to be activated by a focus or hover event. Tooltips can be problematic for some assistive technologies (AT) devices.
Resources
WCAG 2.1 Guidelines
1.3.1 Info and Relationships - Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text. (Level A)
2.4.6 Headings and Labels - Headings and labels describe topic or purpose. (Level AA)
3.3.2 Labels or Instructions - Labels or instructions are provided when content requires user input. (Level A)
4.1.2 Name, Role, Value - For all user interface components (including but not limited to: form elements, links and components generated by scripts), the name and role can be programmatically determined; states, properties, and values that can be set by the user can be programmatically set; and notification of changes to these items is available to user agents, including assistive technologies. (Level A)
Option #1: Simple tooltip with no JS
Option #2: Tooltip with a link
What is Beethoven's favorite fruit? A ba-na-na-na.Option #3: Tooltip with a button
They make up everything!Option #4: Input with right tooltip
He couldn't see himself doing it.<section class="tooltips">
<h3>Option #1: Simple tooltip with no JS</h3>
<form action="#" class="no-js-tooltip">
<fieldset>
<legend>Login</legend>
<div>
<label for="username">Username</label>
<input type="text" id="username" aria-describedby="username-tip" required />
<div role="tooltip" id="username-tip">Try your email address</div>
</div>
<div>
<label for="password">Password</label>
<input type="text" id="password" aria-describedby="password-tip" required />
<div role="tooltip" id="password-tip">It is most likely 1234</div>
</div>
</fieldset>
</form>
<div class="break"></div>
<h3>Option #2: Tooltip with a link</h3>
<span class="a11y-tip a11y-tip--no-delay">
<a href="#" class="a11y-tip__trigger">
What is Beethoven's favorite fruit?
</a>
<span role="tooltip" class="a11y-tip__help a11y-tip__help--top">
A ba-na-na-na.
</span>
</span>
<div class="break"></div>
<h3>Option #3: Tooltip with a button</h3>
<span class="a11y-tip">
<button type="button" class="a11y-tip__trigger" aria-describedby="tt_id">
Don't trust atoms
</button>
<span id="tt_id" role="tooltip" class="a11y-tip__help a11y-tip__help--bottom">
They make up everything!
</span>
</span>
<div class="break"></div>
<h3>Option #4: Input with right tooltip</h3>
<label for="test">
Why did the invisible man turn down the job offer?
</label>
<span class="a11y-tip">
<input id="test" class="a11y-tip__trigger" aria-describedby="test_desc" type="text">
<span id="test_desc" role="tooltip" class="a11y-tip__help a11y-tip__help--right">
He couldn't see himself doing it.
</span>
</span>
</section>
Copied!