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-liveregions ("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
- Automated scan — axe DevTools, Lighthouse accessibility audit, or WAVE. Catches ~30–40% of issues; false positives happen.
- Keyboard pass — tab, shift-tab, enter, space, escape through every flow.
- Screen reader spot check — NVDA on Windows, VoiceOver on macOS/iOS, or TalkBack on Android. Listen for unnamed buttons and skipped headings.
- Zoom to 200% — content should reflow without horizontal scroll and without hidden controls.
- 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-visiblereplacement. - Auto-playing carousels with no pause button.
aria-hiddenon 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-visiblestyles; 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.
langattribute on<html>; page title describes purpose.- Automated scan + manual keyboard and screen-reader pass before ship.
Related reading
- Core Web Vitals explained — performance metrics that overlap with usable UX
- JSON-LD structured data for articles — machine-readable page semantics
- Content Security Policy explained — hardening pages without breaking scripts
- All Solana Garden guides