Web Accessibility Basics-Building Accessible Front-End Applications

Table of contents
- 1. Text Alternatives (alt Attribute)
- 2. Labels and Roles (ARIA Roles)
- 3. Form Elements
- 4. Keyboard Navigation
- 5. Color Contrast
- 6. Visually Hidden Content
- 7. ARIA Live Regions
- 8. Time-Sensitive Content
- 9. Touch Device Considerations
- 10. Semantic Coding
- 11. Visual Indicators
- 12. Voice Commands and Input
- 13. Font and Text Readability
- 14. Clear State for Interactive Elements
- 15. Colorblind Users
- 16. Visual Aids
- 17. Screen Reader Compatibility
- 18. Responsive Design
- 19. Video and Audio Content
- 20. Regular Testing
- 21. Image Maps
- 22. Text-to-Speech
- 23. Error Messages and Feedback
- 24. Focus Management for Interactive Elements

Web Accessibility ensures that websites and applications are equally usable by everyone, including those with visual, auditory, motor, or cognitive impairments. Below are foundational principles and code examples for building accessible front-end applications.
1. Text Alternatives (alt Attribute)
Provide descriptive alt
attributes for non-text content (e.g., images) to enable screen reader users to understand the content.
<img src="hero.jpg" alt="A smiling person holding a cup of coffee">
2. Labels and Roles (ARIA Roles)
Use ARIA (Accessible Rich Internet Applications) roles and attributes to enhance accessibility, especially for complex interactive elements.
<button role="button" aria-label="Close">X</button>
3. Form Elements
Ensure form elements have clear labels, associating <label>
with <input>
elements.
<label for="email">Email:</label>
<input type="email" id="email" required>
4. Keyboard Navigation
All interactive elements should be navigable via keyboard, following a natural focus order.
<nav>
<ul>
<li><a href="#home" tabindex="0">Home</a></li>
<li><a href="#about" tabindex="0">About</a></li>
<li><a href="#contact" tabindex="0">Contact</a></li>
</ul>
</nav>
5. Color Contrast
Ensure sufficient color contrast between text and background, avoiding color as the sole means of conveying information.
/* Use tools like WCAG Color Contrast Checker */
body {
color: #000; /* dark text */
background-color: #f8f8f8; /* light background, good contrast */
}
6. Visually Hidden Content
Use a visually-hidden
class to hide content visually while keeping it accessible to screen readers.
.visually-hidden {
position: absolute !important;
clip: rect(0 0 0 0) !important;
width: 1px !important;
height: 1px !important;
padding: 0 !important;
margin: -1px !important;
overflow: hidden !important;
border: 0 !important;
}
<button>
<span class="visually-hidden">Skip to main content</span>
Skip
</button>
7. ARIA Live Regions
Use the aria-live
attribute to notify screen reader users of dynamic page updates.
<div aria-live="polite" aria-atomic="true" class="notification">
<!-- Dynamic content will be inserted here -->
</div>
8. Time-Sensitive Content
Provide deadlines or timers for time-sensitive content.
<p>
This offer expires in:
<span id="countdown"></span>
</p>
<script>
// Update countdown element content
</script>
9. Touch Device Considerations
Ensure touch targets are at least 44x44 pixels and avoid overly tight layouts.
.button {
min-width: 44px;
min-height: 44px;
padding: 10px;
}
10. Semantic Coding
Use semantic HTML elements like <header>
, <nav>
, <main>
, <article>
, <section>
, and <footer>
.
<body>
<header>
<!-- Header content -->
</header>
<main>
<!-- Main content -->
</main>
<footer>
<!-- Footer content -->
</footer>
</body>
11. Visual Indicators
Add visual feedback for interactive elements, such as hover, focus, and active states.
.button {
transition: all 0.3s;
}
.button:hover,
.button:focus,
.button:active {
background-color: #333;
color: #fff;
}
12. Voice Commands and Input
Support voice-controlled devices (e.g., Siri, Google Assistant) by ensuring interfaces are operable via voice commands.
<form action="/search">
<label for="search">Search:</label>
<input type="search" id="search" name="q" placeholder="Voice command: Search...">
<button type="submit">Go</button>
</form>
13. Font and Text Readability
Choose readable fonts with sufficient line height, letter spacing, and font size. Ensure text scaling doesn’t break layouts.
body {
font-family: Arial, sans-serif;
font-size: 16px;
line-height: 1.5;
letter-spacing: 0.05em;
text-rendering: optimizeLegibility;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
14. Clear State for Interactive Elements
Ensure users know when elements are interactive and their interaction state.
input[type="checkbox"]:checked + label::before {
content: '\2713'; /* checkmark character */
}
<input type="checkbox" id="accept" />
<label for="accept">I accept the terms and conditions</label>
15. Colorblind Users
Use color contrast checkers to ensure color combinations are friendly for colorblind users.
.colorblind-friendly {
background-color: #008080;
color: #fff;
}
16. Visual Aids
Provide visual aids like magnifiers, high-contrast modes, or colorblind simulators.
<button id="toggle-high-contrast">Toggle High Contrast</button>
<script>
document.getElementById('toggle-high-contrast').addEventListener('click', function() {
document.body.classList.toggle('high-contrast');
});
</script>
<style>
.high-contrast {
background-color: #000;
color: #fff;
}
</style>
17. Screen Reader Compatibility
Ensure all critical information is readable by screen readers, such as table captions and summaries.
<table>
<caption>Employee List</caption>
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
</tr>
</thead>
<!-- Table rows -->
</table>
18. Responsive Design
Ensure the website performs well across devices and screen sizes, accommodating various access methods.
@media (max-width: 768px) {
/* Mobile-specific styles */
}
19. Video and Audio Content
Provide captions for videos and transcripts for audio.
<video controls>
<source src="movie.mp4" type="video/mp4">
<track kind="captions" src="movie.vtt" srclang="en" label="English">
</video>
20. Regular Testing
Use automated and manual testing tools (e.g., axe, Pa11y, Lighthouse) to regularly check accessibility and improve based on feedback.
21. Image Maps
For images with multiple interactive regions, use image maps to provide clickable areas.
<img src="worldmap.png" usemap="#worldmap" alt="World Map">
<map name="worldmap">
<area shape="rect" coords="0,0,82,126" alt="North America" href="#na">
<area shape="circle" coords="200,100,30" alt="Europe" href="#eu">
<area shape="poly" coords="330,50,380,0,450,50,400,100" alt="Asia" href="#as">
</map>
22. Text-to-Speech
Offer text-to-speech options to allow users to hear page content.
<button id="tts">Read Aloud</button>
<script>
document.getElementById('tts').addEventListener('click', function() {
const textToRead = document.querySelector('main').innerText;
const speech = new SpeechSynthesisUtterance(textToRead);
window.speechSynthesis.speak(speech);
});
</script>
23. Error Messages and Feedback
Provide clear error messages and feedback to help users resolve issues.
<form>
<label for="email">Email:</label>
<input type="email" id="email" required>
<span id="email-error" class="error"></span>
<button type="submit">Submit</button>
</form>
<script>
document.querySelector('form').addEventListener('submit', function(event) {
event.preventDefault();
const emailInput = document.getElementById('email');
const errorSpan = document.getElementById('email-error');
if (!emailInput.checkValidity()) {
errorSpan.textContent = 'Please enter a valid email address.';
} else {
errorSpan.textContent = '';
// Submit form or perform other actions
}
});
</script>
24. Focus Management for Interactive Elements
Ensure keyboard focus flows correctly between elements, avoiding skips or duplicates.
const focusableElements = 'a[href], button, input:not([type="hidden"]), textarea, select, iframe, object, embed, [tabindex="0"], [contenteditable]';
const firstFocusableElement = document.querySelector(focusableElements);
document.addEventListener('DOMContentLoaded', function() {
if (firstFocusableElement) {
firstFocusableElement.focus();
}
});
document.addEventListener('keydown', function(event) {
if (event.key === 'Tab') {
const lastFocusableElement = document.querySelector(`${focusableElements}:last-of-type`);
if (event.shiftKey && document.activeElement === document.body) {
lastFocusableElement.focus();
event.preventDefault();
} else if (!event.shiftKey && document.activeElement === lastFocusableElement) {
firstFocusableElement.focus();
event.preventDefault();
}
}
});
Subscribe to my newsletter
Read articles from Tianya School directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Tianya School
Tianya School
❤️ • Full Stack Developer 🚀 • Building Web Apps 👨💻 • Learning in Public 🤗 • Software Developer ⚡ • Freelance Dev 💼 • DM for Work / Collabs 💬