Web Accessibility: A Developer's Guide to WCAG 2.1

Adam Golan - Feb 16 - - Dev Community

As web developers, ensuring our applications are accessible isn't just about compliance—it's about creating inclusive experiences for all users. This guide will walk you through practical implementations of WCAG 2.1 guidelines, with code examples and testing strategies.

Why Accessibility Matters

15% of the world's population experiences some form of disability. By implementing accessibility features, you're not just following guidelines—you're making the web usable for:

  • People with visual impairments using screen readers
  • Users with motor disabilities navigating via keyboard
  • Individuals with cognitive disabilities requiring clear layouts
  • People with temporary disabilities (like a broken arm)
  • Elderly users who might struggle with small text or complex interactions

Key WCAG 2.1 Principles

1. Perceivable

Text Alternatives

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

<!-- Good -->
<img src="logo.png" alt="Company Logo - A blue shield with a white star">
Enter fullscreen mode Exit fullscreen mode

Audio/Video Content

<!-- Video with captions and transcripts -->
<video controls>
  <source src="video.mp4" type="video/mp4">
  <track kind="captions" src="captions.vtt" srclang="en" label="English">
  <track kind="descriptions" src="descriptions.vtt" srclang="en" label="English">
</video>
Enter fullscreen mode Exit fullscreen mode

Color and Contrast

/* Ensure sufficient color contrast (minimum 4.5:1 for normal text) */
.readable-text {
  color: #333; /* Dark gray */
  background-color: #fff;
}

/* Don't rely solely on color to convey information */
.error-field {
  border: 2px solid #ff0000;
  background-image: url('error-icon.svg');
}
Enter fullscreen mode Exit fullscreen mode

2. Operable

Keyboard Navigation

// Ensure custom components are keyboard accessible
const CustomButton = () => {
  return (
    <div 
      role="button"
      tabIndex={0}
      onKeyDown={(e) => {
        if (e.key === 'Enter' || e.key === ' ') {
          // Handle activation
        }
      }}
    >
      Click Me
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Time Limits

// Allow users to extend or disable time limits
function sessionTimeout() {
  const timeLeft = 300; // 5 minutes

  if (timeLeft < 60) {
    showWarning();
    offerExtension();
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Understandable

Clear Labels and Instructions

<form>
  <label for="dob">Date of Birth</label>
  <input 
    type="date" 
    id="dob" 
    name="dob"
    aria-describedby="dob-format"
  >
  <span id="dob-format">Format: MM/DD/YYYY</span>
</form>
Enter fullscreen mode Exit fullscreen mode

Consistent Navigation

/* Keep navigation consistent across pages */
.main-nav {
  position: sticky;
  top: 0;
  /* Ensure sufficient clickable area */
  padding: 1rem;
}
Enter fullscreen mode Exit fullscreen mode

4. Robust

Semantic HTML

<!-- Use semantic elements instead of generic divs -->
<header>
  <nav>
    <ul>
      <li><a href="#home">Home</a></li>
    </ul>
  </nav>
</header>
<main>
  <article>
    <h1>Main Content</h1>
    <section>
      <h2>Section Title</h2>
      <!-- Content -->
    </section>
  </article>
</main>
<footer>
  <!-- Footer content -->
</footer>
Enter fullscreen mode Exit fullscreen mode

ARIA When Needed

<!-- Use ARIA when semantic HTML isn't sufficient -->
<div 
  role="alert"
  aria-live="polite"
  class="notification"
>
  Your changes have been saved
</div>
Enter fullscreen mode Exit fullscreen mode

Testing Tools and Strategies

Automated Testing

// Using Jest and Testing Library
describe('Accessibility tests', () => {
  it('should have no accessibility violations', async () => {
    const { container } = render(<MyComponent />);
    const results = await axe(container);
    expect(results).toHaveNoViolations();
  });
});
Enter fullscreen mode Exit fullscreen mode

Manual Testing Checklist

  1. Keyboard Navigation

    • Tab through all interactive elements
    • Ensure visible focus indicators
    • Check skip links functionality
  2. Screen Reader Testing

    • Test with NVDA (Windows)
    • Test with VoiceOver (Mac)
    • Verify proper heading hierarchy
  3. Visual Inspection

    • Test color contrast
    • Verify text remains readable at 200% zoom
    • Check responsive behavior

Common Pitfalls to Avoid

  1. Relying on color alone to convey information
  2. Using generic click handlers instead of semantic buttons
  3. Missing form labels or using placeholder text as labels
  4. Forgetting to include skip links for keyboard users
  5. Not providing alternatives for time-based media
  6. Using improper heading hierarchy

Resources and Tools

Conclusion

Implementing accessibility isn't a one-time task—it's an ongoing process that should be integrated into your development workflow. Start with the basics, test regularly, and gradually enhance your applications to provide a better experience for all users.

Remember: good accessibility benefits everyone, not just users with disabilities. Many accessibility features, like keyboard navigation and clear contrast, improve the user experience for all visitors to your site.

Want to dive deeper? Check out the official WCAG 2.1 documentation or join the accessibility community on WebAIM's discussion forum.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .