Why accessibility matters
Accessibility means building for people who use assistive technology, navigate by keyboard, need higher contrast or prefer reduced motion. Around one in six people live with a disability, and almost everyone benefits from accessibility at some point — a broken arm, a bright screen, a noisy train.
It is also increasingly required. Legislation and procurement rules in many countries reference WCAG, so accessibility is a professional baseline, not a nice-to-have. The reassuring part is that most of it comes from doing the basics well.
WCAG and POUR
The Web Content Accessibility Guidelines define the standard. Their four principles are:
- Perceivable — content can be perceived, for example text alternatives for images and enough contrast.
- Operable — everything works by keyboard and does not require precise pointing.
- Understandable — content and behaviour are predictable and clear.
- Robust — it works with current and future user agents and assistive technology.
Each principle has testable success criteria at levels A, AA and AAA. Most teams target AA.
Semantic HTML is the foundation
Most accessibility comes from using the right elements. Native elements carry roles, states and keyboard behaviour with them.
<!-- semantics.html -->
<header>
<nav aria-label="Main">
<a href="/">Home</a>
</nav>
</header>
<main>
<h1>Dashboard</h1>
<button type="button" aria-expanded="false">Filters</button>
</main>
A <button> is focusable, responds to Enter and Space, and is announced as a button. A <div onclick> is none of those. This is why the Semantic HTML guide comes before this one: semantics are the cheapest accessibility win available.
Keyboard support
Every interactive element must be reachable and operable with a keyboard alone.
- Use native controls, which are focusable by default.
- Keep the tab order logical; it should follow the visual order.
- Provide a skip link so users can bypass repeated navigation.
- Never trap focus inside a component without an escape.
- Show a clear focus indicator and never remove outlines without a visible replacement.
<!-- skip.html -->
<a href="#main" class="skip-link">Skip to content</a>
<main id="main" tabindex="-1">...</main>
Focus management
Focus is the keyboard user’s cursor. Manage it deliberately:
- When a dialog opens, move focus into it and trap it there.
- When it closes, return focus to the element that opened it.
- On client-side navigation, move focus to the new content.
- After validation errors, focus the first invalid field.
Modern dialogs can use the <dialog> element with showModal(), which handles much of this for you.
Text alternatives
Images need text alternatives that convey their purpose in context.
- Informative images get a description of what they convey.
- Decorative images get
alt=""so they are skipped. - Functional images, like an icon inside a link, describe the action.
- Complex images need a longer description nearby.
The same principle applies to media: provide captions for video, transcripts for audio, and labels for every form control.
ARIA, used carefully
ARIA adds semantics that HTML cannot express, but it is easy to misuse. The first rule of ARIA is: do not use ARIA if a native element already does the job. A <div role="button"> is worse than a <button> in almost every way.
When you do need it:
aria-labelnames an element that has no visible text.aria-labelledbyreferences visible text that names the element.aria-describedbylinks a control to a hint or error message.aria-expanded,aria-controlsandaria-livedescribe state and dynamic updates.
Test ARIA with a real screen reader; incorrect ARIA is often worse than none.
Colour and contrast
Text needs enough contrast against its background:
- 4.5:1 for normal text, 3:1 for large text at AA.
- 3:1 for icons, borders and focus indicators.
- Never use colour alone to convey meaning; add text, icons or patterns.
Check contrast with a tool and test your design in grayscale to catch colour-only communication.
Motion and preferences
Respect user preferences.
/* motion.css */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Large parallax and scroll animations are the most common culprits. Also avoid autoplaying media with sound, and provide controls for anything that moves.
Testing
Automated tools catch perhaps a third of issues. Combine them with manual testing:
- Run axe or Lighthouse to catch common violations.
- Navigate with only the keyboard, checking focus and order.
- Zoom to 200% and check nothing breaks or overlaps.
- Try a screen reader: VoiceOver, NVDA or Narrator.
- Check contrast and colour-only meaning.
- Test forms with errors and dynamic content.
The Testing Library guide shows how accessible queries make accessibility part of your test suite.
Best practices
- Start with semantic HTML before adding ARIA.
- Make everything operable by keyboard with visible focus.
- Provide text alternatives for all meaningful media.
- Meet AA contrast and never rely on colour alone.
- Manage focus for dialogs, navigation and errors.
- Respect reduced motion and avoid autoplaying media.
- Test with automated tools and real assistive technology.
Common mistakes
- Using divs as buttons and links.
- Removing focus outlines for aesthetics.
- Missing or unhelpful alt text.
- Adding ARIA incorrectly and breaking native semantics.
- Low-contrast text and colour-only states.
- Ignoring keyboard users in custom widgets.
Where to go next
Accessibility is a practice, not a checklist. Build on Semantic HTML, make forms usable with Forms & Validation, and bake it into tests with Testing Library. Then pick one page, navigate it with only a keyboard, and fix what you find.