Blog Post

Accessibility Best Practices: Building Inclusive Experiences

Creating websites that work for everyone

Web accessibility isn't just a legal requirement—it's a moral imperative and good business practice. Over 1 billion people worldwide have disabilities. Building accessible sites expands your audience, improves SEO, and creates better experiences for everyone.

Understanding WCAG Guidelines

The Web Content Accessibility Guidelines (WCAG) define accessibility through four principles—POUR:

  • Perceivable: Information must be presentable to users in ways they can perceive
  • Operable: Interface components must be operable by all users
  • Understandable: Information and operation must be understandable
  • Robust: Content must work with current and future technologies

WCAG has three conformance levels: A (minimum), AA (recommended), and AAA (enhanced). Target AA compliance for most projects.

Semantic HTML: The Foundation

Semantic elements provide meaning that assistive technologies understand:

<header>
  <nav aria-label="Main navigation">
    <ul>
      <li><a href="/">Home</a></li>
      <li><a href="/about">About</a></li>
    </ul>
  </nav>
</header>

<main>
  <article>
    <h1>Article Title</h1>
    <p>Content here</p>
  </article>
</main>

<footer>
  <p>Copyright information</p>
</footer>

ARIA: Enhancing Accessibility

Accessible Rich Internet Applications (ARIA) attributes provide additional context when semantic HTML isn't enough. Use ARIA sparingly—native HTML is always preferred when available.

Common ARIA attributes:

aria-label: Provides accessible name when visible label doesn't exist:

<button aria-label="Close dialog">
  <span aria-hidden="true">×</span>
</button>

aria-labelledby: References another element for the label:

<h2 id="dialog-title">Confirm Action</h2>
<div role="dialog" aria-labelledby="dialog-title">
  <!-- dialog content -->
</div>

aria-describedby: Provides additional description:

<input 
  type="password" 
  aria-describedby="password-requirements"
>
<span id="password-requirements">
  Must be at least 8 characters
</span>

aria-live: Announces dynamic content changes:

<div aria-live="polite" aria-atomic="true">
  Items added to cart: 3
</div>

Keyboard Navigation: Essential Accessibility

All functionality must be accessible via keyboard. Many users rely exclusively on keyboard navigation due to motor disabilities or preference.

Key requirements:

  • All interactive elements must be focusable with Tab
  • Focus order should follow logical reading order
  • Focus indicator must be clearly visible
  • No keyboard traps (users can tab out of all elements)

Focus styling:

/* Never remove focus outline without replacement */
button:focus {
  outline: 3px solid #0066cc;
  outline-offset: 2px;
}

/* Or use modern focus-visible */
button:focus-visible {
  outline: 3px solid #0066cc;
  outline-offset: 2px;
}

Custom interactive elements need keyboard support:

<div 
  role="button" 
  tabindex="0"
  onclick="handleClick()"
  onkeydown="if(event.key === 'Enter' || event.key === ' ') handleClick()"
>
  Custom Button
</div>

Color Contrast Requirements

WCAG AA requires minimum contrast ratios:

  • Normal text: 4.5:1
  • Large text (18pt+ or 14pt+ bold): 3:1
  • UI components and graphics: 3:1

Use tools like WebAIM Contrast Checker or browser DevTools to verify contrast. Never rely on color alone to convey information:

<!-- Bad: color only -->
<span style="color: red;">Error</span>

<!-- Good: color plus icon/text -->
<span style="color: red;">
  <span aria-hidden="true">⚠️</span>
  Error: Invalid email address
</span>

Forms and Input Accessibility

Forms are critical interaction points that must be fully accessible:

<form>
  <label for="email">Email Address</label>
  <input 
    type="email" 
    id="email" 
    name="email"
    required
    aria-required="true"
    aria-describedby="email-help"
  >
  <span id="email-help">
    We'll never share your email
  </span>
  
  <!-- Error state -->
  <input 
    type="email" 
    id="email" 
    aria-invalid="true"
    aria-describedby="email-error"
  >
  <span id="email-error" role="alert">
    Please enter a valid email address
  </span>
</form>

Best practices:

  • Always associate labels with inputs using for attribute
  • Group related inputs with <fieldset> and <legend>
  • Provide clear error messages associated with fields
  • Use appropriate input types (email, tel, date)
  • Include autocomplete attributes for common fields

Alternative Text for Images

Every image needs alt text—but the content depends on context:

<!-- Informative image -->
<img src="chart.png" alt="Sales increased 25% in Q4">

<!-- Decorative image -->
<img src="decoration.png" alt="" role="presentation">

<!-- Functional image (button/link) -->
<a href="/search">
  <img src="search.png" alt="Search">
</a>

<!-- Complex image -->
<img 
  src="complex-chart.png" 
  alt="Quarterly sales data"
  aria-describedby="chart-description"
>
<div id="chart-description">
  Detailed description of chart data...
</div>

Skip Links: Navigation Shortcuts

Skip links allow keyboard users to bypass repetitive navigation:

<a href="#main-content" class="skip-link">
  Skip to main content
</a>

<!-- CSS -->
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: #000;
  color: white;
  padding: 8px;
  z-index: 100;
}

.skip-link:focus {
  top: 0;
}

Testing for Accessibility

Regular testing is essential:

  • Automated tools: Lighthouse, axe DevTools, WAVE
  • Keyboard testing: Navigate entire site with Tab key only
  • Screen readers: Test with NVDA (Windows), JAWS, or VoiceOver (Mac/iOS)
  • Browser zoom: Test at 200% zoom minimum
  • Color blindness: Use simulators to check for color-only information

Common Mistakes to Avoid

  • Removing focus outlines without replacement
  • Using div or span as buttons instead of <button>
  • Forgetting alt text or writing useless alt text ("image", "photo")
  • Creating keyboard traps in modals or dropdowns
  • Using placeholder as label replacement
  • Setting font sizes in pixels instead of relative units

Accessibility benefits everyone—keyboard users navigate faster, captions help in noisy environments, and clear interfaces reduce cognitive load. Building accessible sites creates better experiences for all users while expanding your reach.