4 min read By Emily Watson

Web Accessibility: A Complete Guide

Learn how to build accessible web applications that everyone can use. Comprehensive guide to WCAG standards and best practices.

Accessibility Web Development Best Practices UX
Web Accessibility: A Complete Guide

Why Accessibility Matters

Web accessibility ensures that websites, tools, and technologies are designed and developed so that people with disabilities can use them. But it benefits everyone.

Understanding WCAG

The Web Content Accessibility Guidelines (WCAG) provide a framework for making content more accessible:

Four Principles: POUR

  1. Perceivable - Information must be presentable to users in ways they can perceive
  2. Operable - User interface components must be operable
  3. Understandable - Information and operation must be understandable
  4. Robust - Content must be robust enough to work with various technologies

Essential Accessibility Practices

Semantic HTML

Use the right HTML elements for the right purpose:

<!-- Good -->
<nav>
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/about">About</a></li>
  </ul>
</nav>

<!-- Bad -->
<div class="nav">
  <div onclick="goHome()">Home</div>
  <div onclick="goAbout()">About</div>
</div>

ARIA Labels

Provide context with ARIA attributes:

<button aria-label="Close dialog">
  <svg aria-hidden="true">...</svg>
</button>

<nav aria-label="Main navigation">
  <!-- Navigation content -->
</nav>

Keyboard Navigation

Ensure all interactive elements are keyboard accessible:

// Trap focus in modal
function trapFocus(element) {
  const focusableElements = element.querySelectorAll(
    'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
  );
  
  const firstFocusable = focusableElements[0];
  const lastFocusable = focusableElements[focusableElements.length - 1];
  
  element.addEventListener('keydown', (e) => {
    if (e.key === 'Tab') {
      if (e.shiftKey && document.activeElement === firstFocusable) {
        lastFocusable.focus();
        e.preventDefault();
      } else if (!e.shiftKey && document.activeElement === lastFocusable) {
        firstFocusable.focus();
        e.preventDefault();
      }
    }
  });
}

Color Contrast

Ensure sufficient color contrast ratios:

  • Normal text: Minimum 4.5:1
  • Large text: Minimum 3:1
  • UI components: Minimum 3:1
/* Good contrast */
.button {
  background: #0066cc;
  color: #ffffff;
  /* Contrast ratio: 8.59:1 */
}

/* Poor contrast */
.bad-button {
  background: #cccccc;
  color: #999999;
  /* Contrast ratio: 2.51:1 - fails WCAG */
}

Testing Tools

Use these tools to audit accessibility:

  1. axe DevTools - Browser extension for automated testing
  2. WAVE - Web accessibility evaluation tool
  3. Lighthouse - Built into Chrome DevTools
  4. Screen readers - NVDA (Windows), VoiceOver (Mac), JAWS
  5. Keyboard testing - Unplug your mouse!

Common Issues to Avoid

Missing Alt Text

<!-- Bad -->
<img src="chart.png">

<!-- Good -->
<img src="chart.png" alt="Bar chart showing 50% increase in sales over Q1">

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

Poor Focus Indicators

/* Bad - removing focus outline */
button:focus {
  outline: none;
}

/* Good - custom focus indicator */
button:focus {
  outline: 3px solid #0066cc;
  outline-offset: 2px;
}

Form Labels

<!-- Bad -->
<input type="email" placeholder="Email">

<!-- Good -->
<label for="email">Email address</label>
<input type="email" id="email" name="email">

Practical Tips

  1. Use headings properly - Maintain hierarchy (h1, h2, h3)
  2. Provide skip links - Let users skip to main content
  3. Make links descriptive - Avoid “click here”
  4. Caption videos - Provide captions and transcripts
  5. Test with real users - Include people with disabilities in testing

Accessibility in React

function AccessibleButton({ onClick, children }) {
  return (
    <button
      onClick={onClick}
      aria-pressed="false"
      className="btn"
    >
      {children}
    </button>
  );
}

function AccessibleForm() {
  const [email, setEmail] = useState('');
  const emailId = useId();

  return (
    <div>
      <label htmlFor={emailId}>Email</label>
      <input
        id={emailId}
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        aria-required="true"
        aria-invalid={!isValidEmail(email)}
      />
    </div>
  );
}

In many countries, web accessibility is legally required:

  • USA: Section 508, ADA
  • EU: European Accessibility Act
  • UK: Equality Act 2010
  • Canada: AODA

Non-compliance can result in lawsuits and penalties.

Conclusion

Accessibility is not optional—it’s a fundamental part of web development. By following WCAG guidelines and testing thoroughly, you can create websites that work for everyone. Remember: accessibility benefits all users, not just those with disabilities.

E

Emily Watson

Published on March 15, 2024

Share: