Guide

Web accessibility (a11y) explained: WCAG, semantic HTML, and ARIA

Web accessibility — often abbreviated a11y (the letters between a and y) — means building sites and apps that people with disabilities can perceive, operate, and understand. That includes users who navigate with a keyboard only, rely on screen readers, need high color contrast, or use voice control. Accessibility is also good engineering: semantic markup improves SEO, keyboard flows catch focus bugs early, and clear labels reduce support tickets. This guide covers the standards, the HTML patterns that solve most problems, when ARIA helps, and how to test without guessing.

Why accessibility matters beyond compliance

Roughly one in six people worldwide lives with a significant disability. Many more experience temporary limitations — a broken arm, bright sunlight on a phone screen, or spotty motor control on a bumpy train. Accessible design serves all of them.

Legal requirements vary by country (ADA in the United States, EAA in the EU), but the technical baseline is shared: the Web Content Accessibility Guidelines (WCAG), maintained by the W3C. Most procurement contracts and lawsuits reference WCAG 2.1 Level AA as the target. Level A covers basics; AA is the practical bar for public sites; AAA is aspirational for specific content like medical instructions.

Search engines reward well-structured pages — headings, alt text, and descriptive link text overlap with what assistive tech needs. Pair accessibility work with Core Web Vitals and structured data for a solid technical SEO foundation.

WCAG at a glance: POUR

WCAG organizes requirements around four principles — remember them as POUR:

  • Perceivable — information is presentable to all senses. Text alternatives for images, captions for video, sufficient contrast, content that reflows without horizontal scrolling.
  • Operable — UI components work with keyboard, voice, and assistive devices. No keyboard traps, enough time to complete tasks, no content that flashes more than three times per second.
  • Understandable — text is readable, navigation is predictable, forms explain errors clearly, language is declared in HTML.
  • Robust — markup parses correctly and works across browsers and assistive technologies today and tomorrow.

You do not memorize every success criterion on day one. Start with the high-impact failures automated tools catch: missing alt text, empty buttons, low contrast, missing form labels, and incorrect heading order.

Semantic HTML: the first 80% of a11y

Browsers ship built-in accessibility for native elements. A real <button> is focusable, activatable with Enter and Space, and announced as a button. A <div onclick> is none of those unless you bolt on tabindex, key handlers, and ARIA — and you will probably get one wrong.

Landmarks and structure

Use one <main> per page for primary content, <nav> for navigation blocks, <header> and <footer> for page chrome, and <article> for self-contained pieces like blog posts. Screen readers expose landmark shortcuts — users jump straight to main or nav instead of tabbing through dozens of links.

Headings are an outline, not styling

Use <h1> through <h6> in order without skipping levels. One <h1> per page is conventional. Do not pick heading levels because a design system font size looks right — use CSS for appearance.

Links vs buttons

<a href> navigates; <button> performs an in-page action. Wallet connect modals, "copy address," and accordion toggles are buttons. "Read the guide" is a link. Mixing them confuses screen readers and breaks middle-click expectations.

Forms that work

Every input needs a visible <label> associated via for/id or wrapping. Placeholder text is not a label — it disappears on focus and often fails contrast. Group related fields with <fieldset> and <legend>. Announce errors with aria-describedby pointing at the error message element.

Keyboard navigation and focus

Unplug your mouse and tab through your site. Every interactive control should receive a visible focus indicator. The CSS property :focus-visible lets you show a strong ring for keyboard users while hiding it for mouse clicks — better than stripping outlines globally, which was a dark pattern of the 2010s.

Tab order and traps

Tab order follows DOM order. Reordering visually with CSS grid without changing DOM order creates cognitive dissonance for keyboard users. Avoid positive tabindex values — they hijack natural flow. Modal dialogs must trap focus inside while open and return focus to the triggering element on close.

Skip links

A "skip to main content" link as the first focusable element saves screen-reader and keyboard users from traversing global navigation on every page load. Hide it off-screen until focused — do not remove it from the tab order.

Custom widgets

Tabs, menus, comboboxes, and carousels have ARIA Authoring Practices patterns defining expected keys (Arrow keys, Home/End, Escape). Copy the pattern before inventing your own keymap.

ARIA: use sparingly, correctly

Accessible Rich Internet Applications (ARIA) attributes extend HTML when native semantics are insufficient — live regions, complex trees, drag-and-drop. The first rule of ARIA: no ARIA is better than bad ARIA. Incorrect role or aria-hidden can silence content entirely.

Common attributes

  • aria-label / aria-labelledby — accessible name when visible text is missing (icon-only buttons need one).
  • aria-expanded — communicates open/closed state for disclosure widgets.
  • aria-live="polite" — announces dynamic updates (toast notifications, form validation) without stealing focus.
  • aria-hidden="true" — hides decorative icons from the accessibility tree. Never hide focusable content.

When not to use ARIA

Do not add role="button" to a <div> when <button> exists. Do not override native roles. Do not use aria-label on elements that already have visible text — prefer the visible text as the name so voice-control users can say what they see.

Visual design constraints

Color contrast

WCAG AA requires 4.5:1 contrast for normal text and 3:1 for large text (18px+ regular or 14px+ bold). UI components and graphical objects need 3:1 against adjacent colors. Never encode meaning with color alone — add icons, patterns, or text labels ("Error: amount required").

Motion and animation

Respect prefers-reduced-motion in CSS to disable parallax, auto-playing carousels, and large transitions for users with vestibular disorders. Auto-playing video needs captions and a pause control.

Touch targets

Interactive targets should be at least 44 by 44 CSS pixels on mobile — close to WCAG 2.2 target size guidance. Tiny icon buttons cramped in toolbars fail both motor-impaired users and everyone with fat fingers.

Images, media, and documents

Informative images need concise alt text describing the content, not the filename. Decorative images use alt="" so screen readers skip them. Complex charts need a longer description nearby or a link to a data table.

Video requires captions (spoken dialogue and meaningful sounds) and ideally transcripts. Audio-only content needs transcripts. PDFs exported from Word often have terrible tag structure — HTML articles like this one are inherently more accessible.

Accessibility in crypto and dApp UIs

Wallet flows add unique challenges: extension popups live outside your DOM, transaction previews use long base58 strings, and status updates arrive asynchronously. Mitigations:

  • Announce connection state changes via aria-live regions ("Wallet connected").
  • Show human-readable summaries alongside raw addresses — truncate with ellipsis but keep full value copyable.
  • Never rely solely on color for success/error — pair green/red with text and icons.
  • Ensure "Connect wallet" is a real <button> reachable by keyboard before the extension opens.
  • Document RPC or network errors in plain language; see Solana RPC endpoints for backend reliability that prevents silent failures.

Testing workflow

  1. Automated scan — axe DevTools, Lighthouse accessibility audit, or WAVE. Catches ~30–40% of issues; false positives happen.
  2. Keyboard pass — tab, shift-tab, enter, space, escape through every flow.
  3. Screen reader spot check — NVDA on Windows, VoiceOver on macOS/iOS, or TalkBack on Android. Listen for unnamed buttons and skipped headings.
  4. Zoom to 200% — content should reflow without horizontal scroll and without hidden controls.
  5. Contrast checker — verify brand colors against backgrounds; fix tokens in your design system, not page by page.

Integrate axe or pa11y into CI for regressions on critical templates. Pair with Content Security Policy testing — strict CSP can block assistive-tech browser extensions if misconfigured, though that is rare on well-scoped policies.

Common mistakes

  • Icon-only buttons with no accessible name.
  • Placeholder-as-label on payment and login forms.
  • Removing focus outlines without a :focus-visible replacement.
  • Auto-playing carousels with no pause button.
  • aria-hidden on a parent that contains focusable children.
  • Tables used for layout instead of data — screen readers announce "table, 47 rows."
  • Infinite scroll with no "load more" alternative or heading landmarks.

Accessibility checklist

  • One <h1>, logical heading hierarchy, semantic landmarks.
  • Native buttons and links; labels on every form field.
  • Visible :focus-visible styles; no keyboard traps in modals.
  • 4.5:1 text contrast (AA); meaning not conveyed by color alone.
  • Alt text on informative images; captions on video.
  • lang attribute on <html>; page title describes purpose.
  • Automated scan + manual keyboard and screen-reader pass before ship.

Related reading