NC Logo UseToolSuite
Web Performance

Web Accessibility Checklist: A Practical Guide for Developers

A no-nonsense web accessibility checklist for developers. Covers WCAG 2.1 essentials, semantic HTML, keyboard navigation, color contrast, screen readers, ARIA, and automated testing tools.

Necmeddin Cunedioglu Necmeddin Cunedioglu

Practice what you learn

Color Converter

Try it free →

I shipped a client project last year that looked beautiful. Smooth animations, perfect color palette, custom fonts. Then the client’s accessibility audit came back: 47 violations. I’d built a site that 15% of the world’s population couldn’t use properly.

Accessibility isn’t a nice-to-have — it’s a legal requirement in many jurisdictions and, honestly, it’s just good engineering. Here’s the checklist I now run through on every project.

The WCAG 2.1 Levels You Need

LevelWhat It CoversWho Needs It
ABasic accessibility (alt text, keyboard access)Everyone — bare minimum
AAEnhanced accessibility (contrast, text resizing)Most legal requirements
AAAMaximum accessibility (sign language, extended descriptions)Specialized needs

Target Level AA. It’s what ADA and EAA reference.

Semantic HTML: The Foundation

Using the right HTML elements is the single highest-impact accessibility improvement. Screen readers rely on semantic meaning.

Use Native Elements Instead of DIVs

<!-- Bad: screen readers don't know this is navigation -->
<div class="nav">
  <div class="nav-item" onclick="navigate('/')">Home</div>
</div>

<!-- Good: screen readers announce "navigation" -->
<nav aria-label="Main navigation">
  <a href="/">Home</a>
  <a href="/about">About</a>
</nav>

Heading Hierarchy

<!-- Bad: heading levels skipped -->
<h1>Page Title</h1>
<h4>Looks right visually</h4>

<!-- Good: proper hierarchy, style with CSS -->
<h1>Page Title</h1>
<h2>Section Title</h2>
<h3>Subsection</h3>

Rules: One <h1> per page. Don’t skip levels. Use CSS for visual sizing.

Landmark Elements

<header>   <!-- Site header -->
<nav>      <!-- Navigation -->
<main>     <!-- Primary content (one per page) -->
<aside>    <!-- Sidebar -->
<footer>   <!-- Site footer -->
<article>  <!-- Self-contained content -->

Keyboard Navigation

Every interactive element must work with keyboard alone.

Focus Visibility

/* Never remove focus without alternative */
:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

:focus-visible shows the ring for keyboard navigation but not mouse clicks.

Use Native Interactive Elements

<!-- Bad: not keyboard-accessible -->
<div class="button" onclick="submit()">Submit</div>

<!-- Good: handles keyboard automatically -->
<button type="submit">Submit</button>

Native <button> handles Enter, Space, focus, and screen reader announcement automatically. Never use positive tabindex values — they override natural DOM order.

Color and Contrast

WCAG Contrast Requirements

ElementMinimum Ratio (AA)
Normal text4.5:1
Large text (≥ 18pt)3:1
UI components3:1

Check your colors: Use our Color Converter to get RGB values and calculate contrast. Our Color Palette Generator creates harmonious schemes — just verify each combination meets WCAG requirements.

Don’t Rely on Color Alone

<!-- Bad: only color indicates error -->
<input style="border-color: red;" />

<!-- Good: color + icon + text -->
<input aria-describedby="email-error" />
<span id="email-error" role="alert">
  ⚠️ Please enter a valid email address
</span>

About 8% of men have color vision deficiency. Always pair color with text or icons.

Images and Media

Alt Text

<!-- Informative: describe content -->
<img src="chart.png" alt="Sales increased 40% in Q3" />

<!-- Functional: describe action -->
<img src="search.png" alt="Search" />

<!-- Decorative: empty alt -->
<img src="border.png" alt="" />

Video Captions

<video controls>
  <source src="demo.mp4" type="video/mp4" />
  <track kind="captions" src="captions.vtt"
         srclang="en" label="English" default />
</video>

ARIA: Use Sparingly

The first rule of ARIA: don’t use ARIA if a native HTML element works.

ARIA You’ll Actually Use

<!-- Live regions for dynamic content -->
<div aria-live="polite">3 items added to cart</div>

<!-- Labels without visible text -->
<button aria-label="Close dialog">
  <svg><!-- X icon --></svg>
</button>

<!-- Expanded/collapsed state -->
<button aria-expanded="false" aria-controls="menu">Menu</button>

Testing

Automated (catches ~30%): axe DevTools, Lighthouse, eslint-plugin-jsx-a11y

Manual (catches ~70%):

  1. Keyboard-only navigation (unplug mouse, use Tab/Enter/Space)
  2. Screen reader testing (VoiceOver, NVDA)
  3. 200% zoom — no horizontal scrolling
  4. Reduced motion preference respected

The Quick Checklist

  • One <h1> per page with proper heading hierarchy
  • All interactive elements keyboard-accessible
  • Focus indicators visible (:focus-visible)
  • All images have appropriate alt attributes
  • Color contrast meets 4.5:1 for text, 3:1 for UI
  • Information not conveyed by color alone
  • Forms have associated labels
  • Error messages announced (role="alert")
  • Page language declared (<html lang="en">)
  • Touch targets at least 44×44px
  • prefers-reduced-motion respected
  • Skip navigation link provided

Further Reading


Building accessible interfaces? Use our Color Converter to verify contrast ratios, HTML Formatter for clean semantic markup, and Meta Tag Generator for accessible page metadata.

Necmeddin Cunedioglu
Necmeddin Cunedioglu Author

Software developer and the creator of UseToolSuite. I write about the tools and techniques I use daily as a developer — practical guides based on real experience, not theory.