Developers

Quick Wins

Semantics First

Use native HTML elements whenever possible (button, a, input, nav, main). Avoid ARIA unless you know exactly why it’s needed. Custom components increase accessibility risk.

Keyboard Support

All interactive elements must work with a keyboard. Tab, Shift+Tab, Enter, and Space must be supported. If it requires a mouse, it’s not accessible.

The First Rule of ARIA

Don’t use ARIA when native HTML already works. Never use ARIA to fix broken markup. ARIA adds meaning — it doesn’t replace semantics.

Focus Management

Focus must always be visible.
Move focus when context changes (modals, errors, navigation). Return focus to a logical place when overlays close.

Accessible Names

Buttons, links, and inputs must have clear names. Icons need accessible names too.
Placeholders are not labels.

HTML

If a native HTML element exists, use it. ARIA should not be your first solution.

Stop and fix if you see this 🚨

❌ Click handlers on div or span

❌ Focus disappears after an action

❌ ARIA added “just in case”

❌ Hover-only or mouse-only interactions

❌ Keyboard users blocked from completing a task

❌ Color used as the only indicator of state

Code Examples​

Bad Practice (Non-semantic)


Inaccessible to keyboards and screen readers.

				
					<div class="btn" onclick="submit()">
     Submit Form
</div>
				
			

✅ Best Practice (Semantic)


Native support for focus, Space/Enter activation.

				
					<button type="button" onClick="submit()">
      Submit Form
</button>
				
			

❌ Bad Practice (Placeholder as label, no error association)


No programmatic label; Error is not announced; Screen reader users don’t know what went wrong

				
					<input type="email" placeholder="Email address">
<span class="error">Invalid email</span>
				
			

✅ Best Practice (Label + associated error)


Visible label; Error is programmatically associated; Screen readers announce the error correctly

				
					<label for="email">Email address</label>
<input id="email" type="email" aria-describedby="email-error" aria-invalid="true" />
<span id="email-error" class="error">
  Enter a valid email address.
</span>
				
			

What to check in your code (before production)

Structure & landmarks

  • One <main> per page
  • Logical heading order (h1 → h2 → h3)
  • Navigation wrapped in <nav>
  • Headings not skipped for visual styling

Interactive elements

  • Buttons are buttons (not divs)
  • Links go somewhere; buttons do something
  • Disabled states are clear and perceivable

Forms

  • Every input has a visible <label>
  • Required fields are clearly indicated
  • Instructions are associated with inputs
  • Placeholders are not used as labels

Errors & Validation

  • Error messages are clear and specific
  • Errors are programmatically associated
  • Error summaries receive focus when present

Dynamic Content

  • Users are informed when content changes
  • aria-live is used intentionally
  • No unexpected context changes

Accessibility Smoke Test

Automated Scan

Ran Axe DevTools and fixed all critical/serious issues

Tab Order

Tab through the page — no dead ends or traps

Visible Focus

Always know where focus is

Zoom (200%)

Content reflows without breaking

Tools for Developers (use these regularly)​

Axe DevTools 

(Chrome/Edge Extension) Catch common issues quickly

Lighthouse (Chrome DevTools)

Baseline accessibility score and insights

Accessibility Tree (Chrome DevTools)

Inspect how assistive tech sees your UI

ESLint-plugin-jsx-a11y

Catch accessibility issues at lint time

References

Technical specifications and authoring practices for complex components

W3C ARIA Authoring Practices (APG)

The official “cookbook” for accessibility. Copy-paste patterns for tabs, accordions, and modals

WCAG 2.2 Quick Reference

A filterable list of all Success Criteria. Great for checking specific requirements

Inclusive Components

Real-world accessibility patterns explained with HTML, CSS, and JavaScript.
Focused on behavior, keyboard interaction, and semantics.