Jonatan Matajonmatum.com
conceptsnotesexperimentsessays
© 2026 Jonatan Mata. All rights reserved.v2.1.1
Concepts

Accessibility

Practice of designing and developing digital products usable by all people, including those with visual, auditory, motor, or cognitive disabilities.

evergreen#accessibility#a11y#wcag#aria#inclusive-design#web

What it is

Web accessibility (a11y) is the practice of making digital products usable by all people, regardless of their abilities. It's not an optional feature — it's a fundamental quality requirement and, in many jurisdictions, a legal one.

Approximately 16% of the world's population lives with some form of disability (WHO). Designing without considering accessibility actively excludes one in six people.

WCAG 2.2 — the current standard

The Web Content Accessibility Guidelines (WCAG) are the international standard published by the W3C. Version 2.2, published in October 2023, adds 9 new success criteria over version 2.1, focused on cognitive accessibility, mobile usability, and authentication.

Three conformance levels:

  • A: minimum (basic contrast, alt text)
  • AA: recommended and legally required in most regulations (4.5:1 contrast, complete keyboard navigation)
  • AAA: optimal (7:1 contrast, simple language)

New criteria in WCAG 2.2

CriterionLevelWhat it addresses
Focus Not Obscured (Minimum)AAFocused element cannot be completely hidden by other elements
Focus Not Obscured (Enhanced)AAAFocused element must be fully visible
Focus AppearanceAAAFocus indicator with minimum area and contrast
Dragging MovementsAAAll drag functionality must have a non-dragging alternative
Target Size (Minimum)AATouch targets at least 24x24 CSS pixels
Consistent HelpAHelp mechanisms in the same relative position across pages
Redundant EntryADon't ask users to re-enter previously provided information
Accessible Authentication (Minimum)AANo cognitive function tests (e.g., transcribing CAPTCHAs) for authentication
Accessible Authentication (Enhanced)AAANo cognitive tests of any kind in the authentication flow

Most regulations (ADA in the US, EN 301 549 in Europe, European Accessibility Act effective June 2025) require level AA as a minimum.

POUR principles

The four principles that organize all WCAG criteria:

  1. Perceivable: content perceivable by at least one sense — alt text, sufficient contrast, video captions
  2. Operable: keyboard navigable, no focus traps, sufficient time to interact
  3. Understandable: clear language, predictable behavior, input error assistance
  4. Robust: compatible with current and future assistive technologies

ARIA patterns in practice

Semantic HTML is always the first choice. ARIA (Accessible Rich Internet Applications) is used when native HTML cannot express a component's role or state.

Rules of ARIA

  1. If you can use native HTML, use it — <button> instead of <div role="button">
  2. Don't change native semantics — don't put role="heading" on a <button>
  3. All interactive controls must be keyboard operable
  4. Don't use role="presentation" or aria-hidden="true" on focusable elements
  5. All interactive elements must have an accessible name

Example: accessible tabs

function Tabs({ tabs, activeTab, onChange }: TabsProps) {
  return (
    <div>
      <div role="tablist" aria-label="Sections">
        {tabs.map((tab, i) => (
          <button
            key={tab.id}
            role="tab"
            id={`tab-${tab.id}`}
            aria-selected={activeTab === tab.id}
            aria-controls={`panel-${tab.id}`}
            tabIndex={activeTab === tab.id ? 0 : -1}
            onClick={() => onChange(tab.id)}
            onKeyDown={(e) => {
              if (e.key === 'ArrowRight') onChange(tabs[(i + 1) % tabs.length].id);
              if (e.key === 'ArrowLeft') onChange(tabs[(i - 1 + tabs.length) % tabs.length].id);
            }}
          >
            {tab.label}
          </button>
        ))}
      </div>
      {tabs.map((tab) => (
        <div
          key={tab.id}
          role="tabpanel"
          id={`panel-${tab.id}`}
          aria-labelledby={`tab-${tab.id}`}
          hidden={activeTab !== tab.id}
        >
          {tab.content}
        </div>
      ))}
    </div>
  );
}

Key points: role="tablist" groups the tabs, aria-selected indicates the active one, aria-controls connects tab to panel, and arrow keys enable keyboard navigation without Tab.

Automated vs manual testing

Automated tools detect between 30% and 40% of accessibility issues — those verifiable by code analysis (contrast, missing alt text, invalid ARIA roles). The remaining 60-70% requires human judgment: is the alt text meaningful? Does the reading order make sense? Is keyboard navigation logical?

AspectAutomatedManual
WCAG coverage30-40% of criteria100% of criteria
SpeedSecondsHours
ConsistencyDeterministicDepends on evaluator
DetectsContrast, missing alt, invalid ARIA, HTML structureReading order, alt text quality, keyboard flows, comprehensibility
Toolsaxe-core, Lighthouse, eslint-plugin-jsx-a11yScreen readers (NVDA, VoiceOver), keyboard navigation, expert review
WhenOn every commit (CI)Before releases, in periodic audits

The effective strategy combines both: automated in CI/CD to prevent regressions, manual before each release to validate the real experience.

axe-core integration in CI

axe-core by Deque is the most widely used accessibility testing engine. It integrates with Playwright, Cypress, Jest, and as a GitHub Action.

With Playwright

import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
 
test('homepage has no accessibility violations', async ({ page }) => {
  await page.goto('/');
  const results = await new AxeBuilder({ page })
    .withTags(['wcag2a', 'wcag2aa', 'wcag22aa'])
    .analyze();
  expect(results.violations).toEqual([]);
});

With eslint-plugin-jsx-a11y

{
  "extends": ["plugin:jsx-a11y/recommended"],
  "rules": {
    "jsx-a11y/anchor-is-valid": "error",
    "jsx-a11y/no-autofocus": "warn",
    "jsx-a11y/label-has-associated-control": "error"
  }
}

This plugin catches issues at development time — before code reaches the browser. Combined with axe-core in CI, it covers the full automated layer.

Screen reader testing workflow

For manual testing, VoiceOver (macOS/iOS) and NVDA (Windows) are the most widely used screen readers:

  1. Activate the screen reader — VoiceOver: Cmd + F5 on macOS
  2. Navigate by headings — verify that the h1 → h2 → h3 hierarchy is logical
  3. Tab through — verify all interactive elements are reachable and the order is logical
  4. Test forms — each input must announce its label, errors must be communicated
  5. Test dynamic components — modals, dropdowns, tabs must announce state changes with aria-live or focus management

Why it matters

Accessibility is not a nice-to-have — it is a legal requirement in most markets (ADA, European Accessibility Act, EN 301 549) and an engineering practice that improves quality for all users. An accessible site works better with keyboards, slow connections, small screens, and diverse devices.

From an architecture perspective, accessibility is cheaper when designed from the start. Retrofitting accessibility into an existing design system can require rewriting entire components. Integrating axe-core into CI/CD and using eslint-plugin-jsx-a11y in development prevents regressions without manual effort — but only covers 30-40% of criteria. Manual testing with screen readers remains necessary before each release.

References

  • WCAG 2.2 — W3C, 2023. International web accessibility standard, current version.
  • WAI-ARIA Authoring Practices Guide — W3C. Accessible design patterns and widgets with code examples.
  • What's new in WCAG 2.2 — TetraLogical, 2023. Summary of the 9 new success criteria.
  • axe-core — Deque Systems. Open-source accessibility testing engine, the foundation of most automated tools.
  • A11y Project — Community. Practical resources, checklists, and accessibility patterns.
  • Evaluating Web Accessibility — W3C WAI. Official guide for evaluating web accessibility.
  • Learn Accessibility — Google web.dev. Complete web accessibility course.

Related content

  • Design Systems

    Collection of reusable components, patterns, and guidelines ensuring visual and interaction consistency in digital products at scale.

  • React

    JavaScript library for building user interfaces through declarative, reusable components, with an ecosystem spanning from SPAs to full-stack applications with Server Components.

  • User Experience

    Discipline encompassing every aspect of a person's interaction with a product, system, or service, aiming for usefulness, usability, and satisfaction.

  • Testing Strategies

    Approaches and testing levels for validating software works correctly, from unit tests to end-to-end tests and testing in production.

  • CI/CD

    Continuous Integration and Continuous Delivery/Deployment — practices that automate code integration, testing, and delivery to production. Foundation of modern software engineering.

  • React Headless Menu

    Headless menu component for React with full accessibility, zero styles, and keyboard support. Published on npm.

  • Web Components

    Native web standards for creating reusable, encapsulated components that work in any framework or without one.

Concepts