~/
hackweb.dev
HTML Accessibility (ARIA Basics)
Quiz
⌘K
...
~/
/tutorials
/html/html-accessibility/edit
~ Contribute
Suggest a correction or improvement. The author reviews it before it goes live.
Loading...
Comment
0 / 300
Typo
Grammar
Broken link
Clarify
Code
en/tutorials/html/15html-accessibility
Write
Preview
Diff
# HTML Accessibility (ARIA Basics) Accessibility ensures everyone can use your website — including people with disabilities. ARIA (Accessible Rich Internet Applications) helps bridge gaps when HTML alone isn't enough. ## Why Accessibility? - **Legal requirement** — Many countries mandate accessibility - **Better SEO** — Search engines read accessible code - **Wider audience** — 15% of people have disabilities - **Better UX** — Accessible sites work better for everyone ## Semantic HTML First **Always use semantic HTML before ARIA:** ```html <!-- Bad: Using div with ARIA --> <div role="button" tabindex="0" onclick="handleClick()"> Click me </div> <!-- Good: Using native HTML --> <button onclick="handleClick()">Click me</button> ``` **Why?** Semantic HTML has built-in accessibility. ARIA is a supplement, not a replacement. ## ARIA Roles Roles define what an element is or does: ```html <!-- Landmark roles --> <div role="banner">Header content</div> <div role="navigation">Nav links</div> <div role="main">Main content</div> <div role="contentinfo">Footer content</div> <!-- Widget roles --> <div role="button">Custom button</div> <div role="tab">Tab item</div> <div role="tabpanel">Tab content</div> <div role="alert">Important message</div> ``` **Common roles:** - `banner` — Site header - `navigation` — Nav links - `main` — Main content - `contentinfo` — Footer - `complementary` — Sidebar - `search` — Search functionality - `button` — Interactive button - `tab` — Tab interface - `tabpanel` — Tab content - `alert` — Important messages - `dialog` — Modal dialog - `progressbar` — Progress indicator ## ARIA Labels Labels describe elements for screen readers: ### `aria-label` Provides an accessible name: ```html <button aria-label="Close menu">×</button> <nav aria-label="Main navigation"> <ul> <li><a href="/">Home</a></li> </ul> </nav> <nav aria-label="Footer navigation"> <ul> <li><a href="/privacy">Privacy</a></li> </ul> </nav> ``` ### `aria-labelledby` References another element's text: ```html <h2 id="section-title">Our Services</h2> <div aria-labelledby="section-title"> <p>Service content here...</p> </div> ``` ### `aria-describedby` Provides additional description: ```html <label for="password">Password</label> <input type="password" id="password" aria-describedby="password-help" /> <span id="password-help">Must be at least 8 characters</span> ``` ## ARIA States States change based on user interaction: ### `aria-expanded` Indicates if something is open/closed: ```html <button aria-expanded="false" onclick="toggleMenu()"> Menu </button> <button aria-expanded="true" onclick="toggleMenu()"> Menu </button> ``` ### `aria-hidden` Hides elements from screen readers: ```html <!-- Decorative icon - hide from screen readers --> <span aria-hidden="true">🎨</span> <!-- Hide content visually but keep accessible --> <div aria-hidden="true" style="display: none;"> This is hidden from everyone </div> ``` ### `aria-live` Announces dynamic content changes: ```html <!-- Polite announcement (waits for user to finish) --> <div aria-live="polite">New message received</div> <!-- Assertive announcement (interrupts immediately) --> <div aria-live="assertive">Error occurred!</div> ``` ### `aria-disabled` Indicates element is disabled: ```html <button aria-disabled="true" disabled>Can't click me</button> ``` ## Complete Example Here's an accessible navigation and content example: ```html <!DOCTYPE html> <html lang="en"> <head> <title>Accessible Page</title> </head> <body> <!-- Header --> <header role="banner"> <h1>My Accessible Site</h1> <!-- Main Navigation --> <nav aria-label="Main navigation"> <ul> <li><a href="/" aria-current="page">Home</a></li> <li><a href="/about">About</a></li> <li><a href="/contact">Contact</a></li> </ul> </nav> </header> <!-- Main Content --> <main role="main"> <h2>Welcome</h2> <!-- Accessible Form --> <form> <div> <label for="name">Name (required)</label> <input type="text" id="name" name="name" required aria-required="true" /> </div> <div> <label for="email">Email (required)</label> <input type="email" id="email" name="email" required aria-required="true" aria-describedby="email-help" /> <span id="email-help">We'll never share your email</span> </div> <button type="submit">Submit</button> </form> <!-- Accessible Alert --> <div role="alert" aria-live="assertive" id="form-status"> <!-- Status messages appear here --> </div> </main> <!-- Footer --> <footer role="contentinfo"> <nav aria-label="Footer navigation"> <ul> <li><a href="/privacy">Privacy Policy</a></li> <li><a href="/terms">Terms of Service</a></li> </ul> </nav> <p>© 2026 My Site</p> </footer> <script> // Show status message function showStatus(message) { const status = document.getElementById('form-status'); status.textContent = message; } </script> </body> </html> ``` ## Keyboard Navigation Ensure all interactive elements are keyboard accessible: ```html <!-- Custom button with keyboard support --> <div role="button" tabindex="0" onclick="handleClick()" onkeydown="if(event.key==='Enter'||event.key===' ')handleClick()" > Click me </div> <!-- Skip link for keyboard users --> <a href="#main-content" class="skip-link"> Skip to main content </a> <style> .skip-link { position: absolute; top: -40px; left: 0; background: #000; color: white; padding: 8px; z-index: 100; } .skip-link:focus { top: 0; } </style> ``` ## ARIA Best Practices 1. **Use semantic HTML first** — ARIA is a supplement 2. **Test with screen readers** — NVDA, VoiceOver, JAWS 3. **Provide labels** — All interactive elements need names 4. **Use live regions** — For dynamic content updates 5. **Don't hide focusable elements** — Breaks keyboard navigation ## Common Mistakes 1. **Using ARIA instead of HTML** — Use `<button>` not `role="button"` 2. **Missing labels** — Inputs without labels hurt accessibility 3. **Using aria-hidden on focusable elements** — Breaks keyboard nav 4. **Not testing with screen readers** — Always test real usage 5. **Overusing aria-live** — Too many announcements annoy users
No changes yet
Reset to original
Submit suggestion
cancel