HTML Task
1. Accessible Form Error Identification & Live Regions (WCAG 3.3.1 & 4.1.3)
Scenario:
The university financial aid department requires a multi-step aid application form. When a user submits invalid data, screen reader users often do not realize an error has occurred because the visual error message is injected dynamically without shifting focus or alerting assistive technologies.
Requirements:
- Construct a form containing at least three fields (e.g., Annual Household Income, Tax Filing Status, Dependent Count) with native HTML constraints.
- Link each error message in the summary box directly to its corresponding input field using anchor links (
<a href="#income-field">). - Native HTML Constraints & Labels (WCAG 3.3.2)
- Ensure that Inputs are bound to
<label>elements viaforandidattributes. - Use native constraints (
required,min,max,type="number") provide explicit field requirements.
4. Associates hint texts and inline error elements (<span id="...">) directly with each field.
Get Ade Code’s stories in your inbox
Join Medium for free to get updates from this writer.
Key Standards Tested: WCAG 3.3.1 (Error Identification), WCAG 3.3.2 (Labels or Instructions), WCAG 4.1.3 (Status Messages), ARIA Live Regions.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Financial Aid Application</title>
<style>
.form-group {
margin-bottom: 1.25rem;
}
label {
display: block;
font-weight: bold;
margin-bottom: 4px;
}
.error-summary {
border: 2px solid #c5221f;
background-color: #fce8e6;
padding: 16px;
margin-bottom: 24px;
border-radius: 4px;
}
.error-summary h2 {
margin-top: 0;
color: #c5221f;
font-size: 1.125rem;
}
.error-summary ul {
margin: 0;
padding-left: 20px;
}
.error-summary a {
color: #c5221f;
font-weight: bold;
}
.inline-error {
color: #c5221f;
font-size: 0.875rem;
font-weight: bold;
display: block;
margin-top: 4px;
}
input[aria-invalid="true"] {
border: 2px solid #c5221f;
}
</style>
</head>
<body>
<main>
<h1>Financial Aid Application</h1>
<!-- Error Summary Container (Hidden by default until validation failure) -->
<div
id="error-summary"
class="error-summary"
role="alert"
aria-labelledby="summary-title"
tabindex="-1"
hidden
>
<h2 id="summary-title">There is a problem with your submission</h2>
<ul id="error-list">
<!-- Dynamic links populated via JavaScript -->
</ul>
</div>
<form id="aid-form" novalidate>
<!-- Household Income -->
<div class="form-group">
<label for="income">Annual Household Income ($USD):</label>
<input
name="income"
>
<span style="display:block; font-size: 0.875rem;">Enter total household earnings before taxes.</span>
<span class="inline-error" hidden>Error: Income is required and must be a positive number.</span>
</div>
<!-- Dependent Count -->
<div class="form-group">
<label for="dependents">Number of Dependents:</label>
<input
name="dependents"
>
<span class="inline-error" hidden>Error: Enter a valid number of dependents (5–15).</span>
</div>
<button type="submit">Submit Application</button>
</form>
</main>
<script>
const form = document.getElementById('aid-form');
const errorSummary = document.getElementById('error-summary');
const errorList = document.getElementById('error-list');
form.addEventListener('submit', (e) => {
e.preventDefault();
// Clear previous error state
errorList.innerHTML = '';
errorSummary.hidden = true;
const errors = [];
const incomeInput = document.getElementById('income');
const dependentsInput = document.getElementById('dependents');
// Validate Household Income
if (!incomeInput.value || Number(incomeInput.value) < 0) {
errors.push({
field: incomeInput,
errorId: 'income-error',
message: 'Annual Household Income is required and must be $0 or greater.'
});
}
// Validate Dependents
if (!dependentsInput.value || Number(dependentsInput.value) < 0 || Number(dependentsInput.value) > 15) {
errors.push({
field: dependentsInput,
errorId: 'dependents-error',
message: 'Number of Dependents must be between 0 and 15.'
});
}
// Handle Validation Results
if (errors.length > 0) {
errors.forEach(err => {
// Set ARIA states on inputs
err.field.setAttribute('aria-invalid', 'true');
document.getElementById(err.errorId).hidden = false;
// Create anchor link in error summary box
const li = document.createElement('li');
const anchor = document.createElement('a');
anchor.href = `#${err.field.id}`;
anchor.textContent = err.message;
// Focus target input when error summary link is clicked
anchor.addEventListener('click', (event) => {
event.preventDefault();
err.field.focus();
});
li.appendChild(anchor);
errorList.appendChild(li);
});
// Show Error Summary and shift focus immediately (WCAG 3.3.1 / 4.1.3)
errorSummary.hidden = false;
errorSummary.focus();
} else {
alert('Form submitted successfully!');
}
});
</script>
</body>
</html>2. Color Independent Information & Accessible Status Indicators (WCAG 1.4.1)
Scenario:
You are building an administrative grade book dashboard for a university portal. Currently, the system displays student submission statuses using only color-coded table cells (e.g., green for “Pass”, red for “Fail”, yellow for “Pending”). This violates WCAG 2.2 Success Criterion 1.4.1 (Use of Color) because color-blind users or screen readers cannot discern the status.
Requirements:
- Refactor the table so status information is not conveyed by visual color alone.
- Incorporate explicit visible text labels alongside accessible micro-icons or symbols (
<svg>or unicode) with properaria-hiddenattributes. - Add hidden text dedicated exclusively to screen readers using an accessible
.visually-hiddenCSS pattern oraria-labelattribute to provide full context (e.g., "Status: Failed — Submission Overdue"). - Ensure all state badges or icons maintain a minimum 3:1 contrast ratio against their surrounding backgrounds.
Key Standards Tested: WCAG 1.4.1 (Use of Color), WCAG 1.3.1 (Info and Relationships), accessible hidden content patterns.




