AppMaker Studio
Web

Web Accessibility: A Practical Guide for Developers

Andy
January 27, 2026
9 min read

Web accessibility is no longer a bonus: it's a legal requirement in many countries and above all an ethical issue. Yet too many developers still consider a11y as a constraint. Here's how to integrate it naturally into your workflow.

Why Accessibility Matters

15% of the world's population lives with a disability. Ignoring accessibility means excluding millions of potential users from your applications.

Good accessibility practices improve the experience for everyone: keyboard navigation, readable contrasts, and semantic structure benefit every user.

SEO and accessibility are linked. Google values well-structured sites with alternative content for images and clear heading hierarchy.

WCAG 2.2 Basics

WCAG (Web Content Accessibility Guidelines) defines 4 principles: Perceivable, Operable, Understandable, Robust. Each criterion has 3 levels: A, AA, AAA.

Aim for AA level minimum. This includes: 4.5:1 contrast ratios for text, complete keyboard navigation, alt text for images, and labels for forms.

WCAG 2.2 (2023) adds important criteria: minimum touch target size (24x24 CSS pixels), accessible authentication, and consistent contextual help.

Semantic HTML: Your First Tool

Use the right HTML elements. A <button> is keyboard-clickable and correctly announced by screen readers. A <div onClick> is not.

Structure with <header>, <main>, <nav>, <article>, <aside>, <footer>. These landmarks allow assistive technology users to navigate quickly.

Respect heading hierarchy. One <h1> per page, then <h2>, <h3>... without skipping levels. It's your content outline.

html
<!-- ❌ Bad: inaccessible div soup -->
<div class="header">
  <div class="nav">...</div>
</div>
<div class="content">
  <div class="title">My title</div>
</div>

<!-- ✅ Good: semantic HTML -->
<header>
  <nav aria-label="Main navigation">...</nav>
</header>
<main>
  <h1>My title</h1>
</main>

ARIA: When and How to Use It

ARIA (Accessible Rich Internet Applications) complements HTML when native elements aren't enough. Golden rule: only use ARIA if necessary.

Common roles: role='button' for a non-button interactive element, role='alert' for urgent messages, role='dialog' for modals.

aria-label and aria-labelledby name elements. aria-describedby adds a description. aria-live announces dynamic changes.

tsx
// Accessible component with ARIA
function SearchInput() {
  const [results, setResults] = useState([]);
  
  return (
    <div>
      <label htmlFor="search">Search</label>
      <input 
        id="search"
        type="search"
        aria-describedby="search-hint"
        aria-controls="search-results"
      />
      <p id="search-hint" className="sr-only">
        Type at least 3 characters
      </p>
      <ul 
        id="search-results"
        role="listbox"
        aria-live="polite"
      >
        {results.map(r => (
          <li key={r.id} role="option">{r.title}</li>
        ))}
      </ul>
    </div>
  );
}

Testing and Tools

Integrate accessibility tests into your CI. axe-core with jest-axe or Playwright automatically detects common violations.

Test manually with keyboard: Tab to navigate, Enter/Space to activate, Escape to close. If you're stuck, your users will be too.

Use a screen reader. VoiceOver (Mac), NVDA (Windows free) or TalkBack (Android). 30 minutes of testing reveals issues that automated tools miss.

Conclusion

Accessibility isn't a feature you add at the end. It's a development approach that benefits everyone. Start with semantic HTML, test with keyboard, and improve progressively. Every improvement counts.