</>StackKit
</>StackKit

Developer tutorials & guides

Accessibility icons and diverse users
Accessibility

Web Accessibility Basics: Build Sites Everyone Can Use

Learn WCAG 2.1 fundamentals, semantic HTML, ARIA roles, keyboard navigation, color contrast, and how to test accessibility in your web projects.

S
Sam Rivera
March 24, 20257 min read
#accessibility#wcag#html#frontend#ux

Why Accessibility Matters

Over 1 billion people worldwide live with some form of disability. Web accessibility isn't just about compliance — it's about not locking people out of your product. It also improves SEO, usability for all users, and in many jurisdictions, it's legally required.


The Four WCAG Principles (POUR)

Perceivable — Users can perceive all information Operable — Users can operate the interface Understandable — Users understand content and UI Robust — Works with current and future assistive technologies

WCAG 2.1 Level AA is the standard target for most web applications.


1. Semantic HTML

Use the right HTML element for the job. Screen readers announce the element's role:

<!-- Bad -->
<div onclick="submit()">Submit</div>
<div class="header">My Site</div>
<div class="nav">...</div>

<!-- Good -->
<button type="submit">Submit</button>
<header><h1>My Site</h1></header>
<nav aria-label="Main navigation">...</nav>

Semantic elements provide keyboard interaction and ARIA roles for free.


2. Image Alt Text

<!-- Informative image -->
<img src="chart.png" alt="Bar chart showing 40% increase in revenue Q1 2025" />

<!-- Decorative image — empty alt tells screen readers to skip it -->
<img src="divider.svg" alt="" role="presentation" />

<!-- Icon button — describe the action -->
<button aria-label="Close dialog">
  <svg aria-hidden="true">...</svg>
</button>

3. Keyboard Navigation

All interactive elements must be reachable and operable with a keyboard alone:

<!-- Natural tab order — don't use tabindex > 0 -->
<button>First</button>
<button>Second</button>
<button>Third</button>

<!-- Custom focusable element -->
<div role="button" tabindex="0" onkeydown="handleKey(event)">
  Click me
</div>

Test by pressing Tab through your entire UI. Every interactive element should be reachable, and focus should be clearly visible.


4. Focus Management

When dialogs open, move focus inside them. When they close, return focus to the trigger:

function Dialog({ isOpen, onClose, triggerRef }) {
  const dialogRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (isOpen) {
      dialogRef.current?.focus();
    } else {
      triggerRef.current?.focus();
    }
  }, [isOpen]);

  return isOpen ? (
    <div role="dialog" aria-modal="true" ref={dialogRef} tabIndex={-1}>
      {/* content */}
    </div>
  ) : null;
}

5. Color Contrast

WCAG AA requires:

  • 4.5:1 contrast ratio for normal text
  • 3:1 for large text (18pt+ or 14pt+ bold)

Tools:

Never convey information by color alone — add icons, patterns, or text labels.


6. ARIA Labels and Descriptions

<!-- Label a landmark region -->
<nav aria-label="Breadcrumb">...</nav>

<!-- Describe an input more fully -->
<input
  type="password"
  aria-describedby="pwd-hint"
/>
<p id="pwd-hint">Must be 8+ characters with one number</p>

<!-- Live regions for dynamic updates -->
<div aria-live="polite" aria-atomic="true">
  Form submitted successfully!
</div>

7. Forms

<!-- Associate every input with a label -->
<label for="email">Email address</label>
<input type="email" id="email" name="email" required autocomplete="email" />

<!-- Group related inputs -->
<fieldset>
  <legend>Shipping address</legend>
  <!-- inputs -->
</fieldset>

<!-- Error messages -->
<input
  type="email"
  aria-invalid="true"
  aria-describedby="email-error"
/>
<span id="email-error" role="alert">
  Please enter a valid email address.
</span>

Testing Accessibility

  1. Keyboard only — unplug your mouse and try using your app
  2. Screen reader — VoiceOver (Mac/iOS), NVDA (Windows), TalkBack (Android)
  3. Automated tools — axe DevTools (browser extension), Lighthouse audit
  4. Color blindness simulators — Chrome DevTools → Rendering → Emulate vision deficiencies

Conclusion

Start with semantic HTML and you'll get 60% of accessibility for free. Add proper labels, keyboard navigation, and visible focus states for another 30%. The remaining 10% is nuanced ARIA patterns for complex widgets. Automated tools catch about 30-40% of issues — manual testing with a keyboard and screen reader is irreplaceable.

#accessibility#wcag#html#frontend#ux