Skip to content

Accessibility Fundamentals

I need to... Guide Summary
Structure pages with landmarks and headings Semantic Structure Use <header>, <nav>, <main>, <aside>, <footer> and <h1><h6> in strict sequence; add a skip link targeting <main tabindex="-1">; never label every <section> as a region landmark — more than 6–8 landmarks dilutes their value.
Decide when ARIA is and isn't appropriate ARIA Usage Use native HTML elements first (<button>, <nav>, <ul>); apply ARIA only when no native equivalent exists; when you set an ARIA role you MUST implement its full keyboard behavior or the result is worse than no ARIA at all.
Name interactive elements and landmarks Accessible Names Use <label for="id"> for inputs, <caption> for tables, <figcaption> for figures; prefer aria-labelledby over aria-label when visible text exists — it survives translation and never goes stale.
Handle keyboard navigation and focus Keyboard and Focus Every action reachable by mouse must be reachable by keyboard; use :focus-visible with sufficient contrast; never use positive tabindex values; aria-hidden="true" on a focusable element creates an invisible focus trap.
Announce dynamic content changes Live Regions Maintain two centralized live regions (one polite, one assertive) rather than scattering them per component; use assertive only for critical time-sensitive events; clear then set on next animation frame to guarantee re-announcement.
Build accessible forms with error handling Forms Accessibility Use <label for="id"> for every input, aria-describedby for hints, aria-errormessage+aria-invalid for errors; bridge CSS :user-invalid to aria-invalid via JS so errors only announce after the user has interacted with the field.
Write alt text and caption media Media Alternatives Calibrate alt text to context — functional images describe the action, informative images describe meaning, decorative images get alt=""; inline SVGs need role="img" + <title> when informative; never apply aria-hidden="true" to a focusable element.
Meet contrast and typography requirements Color and Typography Normal text needs 4.5:1 contrast (WCAG AA), UI component boundaries need 3:1; use rem/em for font sizing (never px); always pair color-coded states with an icon or text label.
Respect reduced-motion preferences Motion Preferences Default page state should be static — scope animations inside @media (prefers-reduced-motion: no-preference); slowing down a spinning animation is not sufficient — motion itself is the trigger for vestibular disorders; never exceed 3 flashes/second.
Implement modal dialogs correctly Native Dialog Use <dialog>.showModal() for modals — the browser makes background content inert and handles Escape; never add a custom JS focus trap to a native modal; inert overlay must be a sibling not a descendant of the inerted element.
Set page language, title, and SPA metadata Document Metadata Declare <html lang="en">, front-load unique context in <title> ("Page Topic
Test with automated tools and screen readers Accessibility Testing Automated tools (axe-core, Lighthouse) catch only ~30–40% of issues — supplement with keyboard-only testing and canonical screen-reader pairings: JAWS+Chrome, NVDA+Firefox, VoiceOver+Safari.