Pointer Cancellation
When activating an interactive element, it SHOULD always get activated on up event. Sometimes, the element gets activated on a down event. This causes unintended actions caused by accidental activation of elements.
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.
For functionality that operates using single pointer, at least ONE of the following SHOULD be true.
- Any interactive element SHOULD get activated on up event only.
- The completion of the action SHOULD happen on the up event.
- A mechanism SHOULD be available to abort the action or undo the action.
- The up event SHOULD reverse any outcome of the preceding down-event.
- Only essential functions SHOULD be activated on the down-event.
Note: One of the exceptions where the functionality can be activated on down event is dropdown element where the option gets expanded on down event.
A well-defined element with pointer cancellation majorly benefit the below users.
- People using keyboard only
- People with visual impairments
- People with motor impairments
<form id="registrationForm">
<div class="container">
<h2>Register</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>
<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>
<label for="role_select">Role<span class="span">*</span></label>
<select id="role_select" required>
<option value="">Select a Role</option>
<option value="Educator">Educator</option>
<option value="Learner">Learner</option>
</select>
<button type="button" onclick="validateForm()">Submit</button>
<span class="mt5">
Have a Pearson account? <a href="#"> Sign in.</a>
</span>
</div>
</form>
.container {
display: flex;
flex-direction: column;
width: 30vw;
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;
}
select {
margin: 0.25em 0em 1em 0em;
padding: 13px 12px 14px !important;
border: 1px solid #333;
background: none;
border-radius: 0.25em;
}
button {
padding: 0.75em;
border: none;
background-color: #003057;
color: white;
border-radius: 40px;
font-size: 16px;
}
button:hover { background-color: #037d76; }
button:focus {
outline: .10em solid #000000;
outline-offset: 1px;
}
fieldset {
margin: 0.5em;
border: 1px solid #333;
border-radius: 0.25em;
}
.mt5 { margin: 0.5rem }
@media screen and (max-width: 600px) {
.container { width: 80vw !important; }
}
@media screen and (max-width: 900px) {
.container { width: 50vw !important; }
}
function validateForm() {
let firstname = document.getElementById('firstname');
let option1 = document.getElementById('option1');
let option2 = document.getElementById('option2');
let role_select = document.getElementById('role_select');
let fieldset = document.getElementById('fieldset');
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 (!option1.checked && !option2.checked) {
errorMessage += 'Please select a Gender.\n';
fieldset.classList.add('error');
if (!focusField) {
focusField = option1;
}
} else {
fieldset.classList.remove('error');
}
if (role_select.value === '') {
errorMessage += 'Please select a Role.\n';
role_select.classList.add('error');
if (!focusField) {
focusField = role_select;
}
} else {
role_select.classList.remove('error');
}
if (errorMessage) {
alert(errorMessage);
if (focusField) {
focusField.focus();
}
return false;
}
alert('Form submitted successfully!');
return true;
}