AiTechWorlds
AiTechWorlds
WCAG 2.1 Levels: A (minimum), AA (industry standard), AAA (enhanced)
| Principle | Meaning |
|---|---|
| Perceivable | Users can perceive all content (alt text, captions) |
| Operable | Users can navigate and interact (keyboard, no seizures) |
| Understandable | Content and UI are clear (plain language, consistent nav) |
| Robust | Works with assistive technologies (valid HTML, ARIA) |
<!-- BAD: divs for everything -->
<div class="nav">
<div class="nav-item" onclick="...">Home</div>
</div>
<div class="main">
<div class="title">Welcome</div>
</div>
<!-- GOOD: semantic elements -->
<nav aria-label="Main navigation">
<a href="/">Home</a>
</nav>
<main>
<h1>Welcome</h1>
</main>| Element | Purpose |
|---|---|
| Page/section header |
| Navigation links |
| Primary content (one per page) |
| Self-contained content |
| Thematic grouping with heading |
| Sidebar, supplementary |
| Page/section footer |
/ | Image with caption |
| Machine-readable date |
| Contact information |
<!-- Informative image β describe what it conveys -->
<img src="chart.png" alt="Bar chart showing 40% increase in Q1 sales">
<!-- Decorative image β empty alt (screen reader skips it) -->
<img src="divider.png" alt="">
<!-- Background image β use CSS, not <img> -->
<div style="background-image: url(bg.jpg)" role="img" aria-label="Office building exterior"></div>
<!-- Complex image β link to description -->
<img src="infographic.png" alt="AI adoption trends 2026" aria-describedby="infographic-desc">
<p id="infographic-desc" class="sr-only">Detailed description: ...</p>All interactive elements must be operable via keyboard:
<!-- Use native elements (already keyboard accessible) -->
<button onclick="submit()">Submit</button> β
<a href="/page">Go</a> β
<!-- Custom interactive element β must have tabindex and keyboard handler -->
<div
role="button"
tabindex="0"
onclick="handleClick()"
onkeydown="e.key === 'Enter' || e.key === ' ' ? handleClick() : null"
>
Custom Button
</div>/* Never remove focus outline β restyle it instead */
:focus-visible {
outline: 3px solid #4f46e5;
outline-offset: 2px;
border-radius: 4px;
}
/* Remove only for mouse users, keep for keyboard */
:focus:not(:focus-visible) {
outline: none;
}| Attribute | Use |
|---|---|
aria-label | Accessible name when no visible label exists |
aria-labelledby | Points to element that labels this one |
aria-describedby | Points to element with additional description |
aria-hidden="true" | Hide from screen readers (decorative icons) |
aria-expanded | State of collapsible (true/false) |
aria-current="page" | Current item in nav |
aria-live="polite" | Announce dynamic content updates |
aria-busy="true" | Element is loading |
role="alert" | Important announcement (reads immediately) |
role="dialog" | Modal dialog |
role="tablist" / "tab" | Tab component |
1. Use semantic HTML first β ARIA is a last resort
2. Don't use ARIA to override semantics unnecessarily
3. All ARIA widgets must be keyboard operable
4. Don't hide visible content from screen readers
<!-- Politely announce changes (waits for user idle) -->
<div aria-live="polite" aria-atomic="true" id="status">
<!-- Inject messages here dynamically -->
</div>
<!-- Assertive β interrupt immediately (errors, alerts) -->
<div role="alert">Your session expires in 5 minutes</div><!-- Always associate labels -->
<label for="email">Email address</label>
<input
type="email"
id="email"
name="email"
autocomplete="email"
required
aria-describedby="email-error"
aria-invalid="true"
>
<span id="email-error" role="alert">Please enter a valid email</span>
<!-- Fieldset for grouped inputs -->
<fieldset>
<legend>Notification preferences</legend>
<input type="checkbox" id="email-notif" name="notify" value="email">
<label for="email-notif">Email</label>
<input type="checkbox" id="sms-notif" name="notify" value="sms">
<label for="sms-notif">SMS</label>
</fieldset>| Text Type | Minimum Ratio |
|---|---|
| Normal text (< 18px / not bold) | 4.5:1 |
| Large text (β₯ 18px or β₯ 14px bold) | 3:1 |
| UI components, icons | 3:1 |
| Decorative elements | No requirement |
Test tools: WebAIM Contrast Checker, browser DevTools accessibility panel, axe browser extension.
| Screen Reader | Platform | Cost |
|---|---|---|
| NVDA | Windows | Free |
| JAWS | Windows | Paid |
| VoiceOver | macOS / iOS | Built-in (free) |
| TalkBack | Android | Built-in (free) |
Quick VoiceOver test: Cmd+F5 on Mac, then navigate with Tab and arrow keys.
<!-- First element in <body> -->
<a href="#main-content" class="skip-link">Skip to main content</a>
<style>
.skip-link {
position: absolute;
transform: translateY(-100%);
transition: transform 0.2s;
}
.skip-link:focus {
transform: translateY(0); /* visible when focused */
}
</style>
<main id="main-content">...</main>aria-label on every element β only needed when there's no visible label; overuse clutters screen reader outputAdvertisement
Get more notes like this daily on Telegram!
Free study notes, cheat sheets & AI tips
Last reviewed on June 13, 2026 by the AiTechWorlds Notes Team. Free cheat sheet β no signup required.
Advertisement
Join AiTechWorlds on Telegram and get daily AI tips, prompt engineering templates, coding resources, and exclusive content β 100% free!
No spam. Leave anytime.