Form Control Status
Form controls such as checkboxes, radio buttons, disclosure widgets have different states. Therefore, it is necessary to inform all users about updates to the state of a control when the user interacts with the form controls.
The state information for form controls SHOULD be defined semantically. This ensures that the state information is available for all users.
NOTE:
- New to accessibility or uncertain of requirements, it will be helpful to review all sections below.
- Already familiar with requirements, skip to the “Working Example” section for sample HTML, CSS and JavaScript (when needed), along with a working demo.
-
Native HTML elements such as
<input type="checkbox">
,<input type="radio">
,<input type="range">
and so on, the state information is announced by default. No additional attributes are required.
-
For form controls defined using ARIA, additional attributes SHOULD be
defined for screen readers to identify its state.
For example:-
For two-state checkboxes and radio buttons, provide
aria-checked="false"
. Ensure that the value ofaria-checked
gets updated totrue
orfalse
as per user interaction. -
For tri-state checkboxes, there is an additional state
aria-checked="mixed"
to denote partial checked state. - For sliders, the state information is announced by default. No additional attributes are required.
- For disclosure widgets, provide
aria-expanded
attribute. Set its value tofalse
in order to denote collapsed state. Ensure that its value is updated to true when it is expanded due to user interaction. -
For comboboxes, provide
aria-selected="true"
to indicate the selected option in the custom drop-down list for screen reader users. Ensure that the value of aria-selected attribute is updated as per user’s interaction. -
For tabs, provide
aria-selected="true"
attribute to notify the user of the selected tab. Ensure that the value ofaria-selected
attribute is updated as per user’s interaction.<h1>Tabbed Interfaces </h1> <h2>Tabs with Automatic Activation</h2> <div class="tab-container"> <div class="tab-list" role="tablist"> <button class="tab" id="pearson_pathways" role="tab" aria-controls="tabpanel1" aria-selected="true"> Pearson Pathways </button> <button class="tab" id="pearson_advance" role="tab" aria-controls="tabpanel2" aria-selected="false" tabindex="-1"> Pearson Advance </button> ... </div> <div class="tab-panels"> <div id="tabpanel1" class="tab-panel" role="tabpanel" aria-labelledby="pearson_pathways"> <p> A personalized online search engine and marketplace to help learners compare programs, review customized recommendations, and easily apply </p> <p> Choosing a career in nursing means you never stop learning - you can’t deliver the highest-quality patient care if you aren't up-to date on the latest best practices. And with an accredited online degree or certificate offered by one of our partners, you can develop the clinical, technical, and interpersonal skills to pursue new opportunities in this field. Start exploring careers and programs and reach out if you need support along the way. </p> <a href="https://www.pearson.com/pathways/program-profiles.html" target="_blank"> Browse Programs </a> </div> ... </div> </div>
-
For two-state checkboxes and radio buttons, provide
- The state SHOULD also be conveyed through a visual cue and not rely on color alone. For more information on color alone, refer to Color Alone component.
- The visual cue SHOULD meet the contrast ratio requirement of 3:1 with the adjacent color. For more information on non-text contrast requirements, refer to Color Contrast component.
For more information on the components, refer to:
Form controls with appropriate state information majorly benefits the below users.
- People with visual disabilities
- People with cognitive disabilities
- People using speech input
- People with limited dexterity
- People using keyboard only
<h1>Form control Status</h1>
<button id="toggleFormButton" aria-expanded="false" aria-controls="registrationForm">
Get registered
</button>
<form id="registrationForm" class="hidden">
<div class="container">
<h2>Registration</h2>
<p>Please fill in this form to create an account.</p>
<p>
<strong>Fields marked with asterisk (<span class="span">*</span>)
are mandatory.</strong>
</p>
<label for="firstname">Name<span class="span">*</span></label>
<input type="text" id="firstname" required>
<label for="password">Password<span class="span">*</span></label>
<input type="text" id="password" required>
<div>
<fieldset id="fieldset">
<legend>
<strong>Gender <span class="span">*</span></strong>
</legend>
<input type="radio" id="option1" name="options" value="1" required>
<label for="option1">Male</label>
<input type="radio" id="option2" name="options" value="2" required>
<label for="option2">Female</label>
</fieldset>
</div>
<div class="inline">
<input type="checkbox" id="myCheckbox">
<label for="myCheckbox" style="font-size: 14px;">
I agree to the Terms of Use and acknowledge the Privacy Policy.
</label>
</div>
<button id="submit">Submit</button>
<p class="mt5">
Have a Pearson account?
<a href="https://www.pearson.com/en-us.html"> Sign in.</a>
</p>
</div>
</form>
.hidden { display: none; }
form {
display: flex;
flex-direction: column;
margin-bottom: 5rem;
}
.container {
display: flex;
flex-direction: column;
width: 50vw;
padding: 1rem;
border: 3px solid #7f7f7f;
}
input[type=text] {
margin: 0.25em 0em 1em 0em;
padding: 13px 12px 14px !important;
border: 1px solid #333;
background: none;
border-radius: 0.25em;
}
fieldset {
margin: 0.5em;
border: 1px solid #333;
border-radius: 0.25em;
}
.frm-containor { flex-basis: 50%; }
button {
padding: 0.75em;
border: none;
background-color: #003057;
color: white;
border-radius: 40px;
font-size: 16px;
margin-bottom: 1rem;
margin-top: 1rem;
}
button:hover { background-color: #037d76; }
button:focus {
outline: .10em solid #000000;
outline-offset: 1px;
}
@media screen and (max-width: 600px) {
.container { width: 80%; }
}
const toggleFormButton = document.getElementById('toggleFormButton');
const formContainer = document.getElementById('registrationForm');
const submit = document.getElementById('submit');
toggleFormButton.addEventListener('click', () => {
const expanded = toggleFormButton.getAttribute('aria-expanded') === 'true';
toggleFormButton.setAttribute('aria-expanded', String(!expanded));
formContainer.setAttribute('aria-hidden', String(expanded));
if (expanded) {
formContainer.style.display = 'none';
} else {
formContainer.style.display = 'block';
}
});
submit.addEventListener('click', validateForm);
function validateForm() {
const firstname = document.getElementById('firstname');
const password = document.getElementById('password');
const option1 = document.getElementById('option1');
const option2 = document.getElementById('option2');
const fieldset = document.getElementById('fieldset');
const checkbox = document.getElementById('myCheckbox');
let errorMessage = '';
let focusField = null;
if (!firstname.value) {
errorMessage += 'Please fill out the Name field.\n';
firstname.classList.add('error');
if (!focusField) {
focusField = firstname;
}
} else {
firstname.classList.remove('error');
}
if (!password.value) {
errorMessage += 'Please fill out the Password field.\n';
password.classList.add('error');
if (!focusField) {
focusField = password;
}
} else {
password.classList.remove('error');
}
if (!option1.checked && !option2.checked) {
errorMessage += 'Please select a Gender.\n';
fieldset.classList.add('error');
if (!focusField) {
focusField = option1;
}
} else {
fieldset.classList.remove('error');
}
if(!checkbox.checked){
errorMessage += 'Please agree to the terms of use and privacy policy.\n';
if (!focusField) {
focusField = checkbox;
}
}
if (errorMessage) {
alert(errorMessage);
if (focusField) {
focusField.focus();
}
return false;
}
alert('Form submitted successfully!');
return true;
}