accessibility

Audits web and mobile applications for accessibility compliance (WCAG 2.1). Checks keyboard navigation, screen reader support, color contrast, focus management, and semantic markup. Use when reviewing UI code, building new components, or preparing for accessibility audits.

Accessibility Audit

Accessibility isn't a feature - it's a quality bar. If it doesn't work with a keyboard, a screen reader, or low vision, it's broken.

Quick Checks (Do These First)

1. Keyboard Navigation

  • Tab through the entire page - can you reach every interactive element?
  • Tab order follows visual order (no jumping around)
  • Focus indicator is visible on every focused element
  • Escape closes modals/popups and returns focus to trigger
  • Enter/Space activates buttons and links
  • Arrow keys work in menus, tabs, and custom widgets
  • No keyboard traps (can always Tab away from any element)

2. Screen Reader

  • Every image has alt text (or alt="" for decorative images)
  • Form inputs have associated <label> elements
  • Buttons and links have descriptive text (not "Click here")
  • Page has a single <h1>, heading hierarchy doesn't skip levels
  • Dynamic content changes announced (ARIA live regions)
  • Custom components have appropriate ARIA roles and states

3. Visual

  • Text contrast ratio ≥ 4.5:1 (normal text) or ≥ 3:1 (large text)
  • Information not conveyed by color alone (add icons, patterns, text)
  • Text resizable to 200% without loss of content
  • UI functional at 320px width (mobile) without horizontal scroll
  • Animations respect prefers-reduced-motion

Semantic HTML

Use the right element. It gets you keyboard and screen reader support for free.

NeedUseNOT
Navigation<nav><div class="nav">
Button<button><div onClick> or <a href="#">
Link (navigate)<a href="..."><button> or <span onClick>
List<ul>/<ol>Divs with bullet characters
Heading<h1>-<h6><div class="heading">
Form field<input> + <label><div contenteditable>
Table data<table> + <th>Divs in a grid layout
Main content<main><div id="content">

Rule: If you're adding ARIA attributes to make a <div> behave like a button, you should just use a <button>.

ARIA Usage

ARIA is a last resort, not a first choice. Semantic HTML first.

When ARIA Is Needed

  • Custom widgets with no HTML equivalent (tabs, combobox, tree view)
  • Dynamic content updates (live regions)
  • Relationships between elements that markup can't express

Common Patterns

<!-- Tabs -->
<div role="tablist">
  <button role="tab" aria-selected="true" aria-controls="panel-1">Tab 1</button>
  <button role="tab" aria-selected="false" aria-controls="panel-2">Tab 2</button>
</div>
<div role="tabpanel" id="panel-1">Content 1</div>

<!-- Modal -->
<div role="dialog" aria-modal="true" aria-labelledby="modal-title">
  <h2 id="modal-title">Modal Title</h2>
  <!-- Focus trapped inside modal -->
</div>

<!-- Live region (for dynamic updates) -->
<div aria-live="polite">
  <!-- Screen reader announces changes here -->
  3 items added to cart
</div>

<!-- Loading state -->
<button aria-busy="true" aria-disabled="true">
  <span aria-hidden="true">⏳</span> Loading...
</button>

Focus Management

ScenarioFocus Should Go To
Modal opensFirst focusable element inside modal
Modal closesElement that triggered the modal
Item deleted from listNext item in list (or previous if last)
Page navigation (SPA)Page heading or main content
Error on form submitFirst field with an error
Accordion expandsThe expanded content

Color Contrast

ElementMinimum RatioCheck
Normal text (< 18px)4.5:1Required
Large text (≥ 18px bold or ≥ 24px)3:1Required
UI components (borders, icons)3:1Required
Decorative elementsNo requirement-

Tools: Chrome DevTools (Inspect → color picker shows ratio), axe DevTools extension, WebAIM Contrast Checker.

Testing Tools

ToolWhat It Catches
axe DevTools (browser extension)~30-40% of WCAG issues automatically
Lighthouse AccessibilityHigh-level score + common issues
Keyboard (manual)Navigation, focus, traps
Screen reader (manual)Content order, announcements, labels
Zoom to 200% (manual)Layout issues at larger text sizes

Automated tools catch < 50% of issues. Manual testing with keyboard + screen reader is required.

Output

[CRITICAL] - [element/page] - [issue] - [WCAG criterion] - [fix]
[SERIOUS]  - [element/page] - [issue] - [WCAG criterion] - [fix]
[MODERATE] - [element/page] - [issue] - [WCAG criterion] - [fix]
[MINOR]    - [element/page] - [issue] - [WCAG criterion] - [fix]