Skip to main content

Accessibility

Our goal with accessibility testing is to ensure that a website is accessible and usable by all users. This includes auditing issues that arise with third-party viewing aids (like screen readers) and things those tools may not catch (like contrast and font size).

Standards

Our baseline commitment is WCAG 2.2 AA and Section 508 compliance on every project. Clients will know if they require more stringent standards (e.g., WCAG AAA) — when that's the case, scope it explicitly in the project agreement.

Testing Tools

Automated tests find a lot, but they don't catch everything — especially content-related issues. Use a combination of automated and manual testing on every audit.

Accessibility Insights

A browser extension from Microsoft. Runs WCAG 2.2 AA checks by default. Use it for a quick automated sweep before doing manual checks.

WAVE

Available as a Chrome and Firefox extension. Evaluates web content for accessibility issues directly in the browser, with inline visual feedback.

Pa11y

A command-line accessibility testing tool.

# Install
npm i -g pa11y

# Test a page against both standards
pa11y --standard Section508 --standard WCAG2AA https://example.com

Koa11y

A GUI wrapper around Pa11y for those who prefer not to use the CLI. Download and move to ~/Applications, then enter a URL and click "Run."

Screen Readers

Test across browser/screen reader combinations:

Screen ReaderBrowser
VoiceOverSafari (macOS/iOS)
NVDAFirefox
JAWSInternet Explorer or Edge

Color Contrast Checker

Goal: pass both AA (minimum) and AAA (desired). Use any WCAG-compliant contrast checker to evaluate foreground/background color pairs.

Keyboard Testing

Goal: full keyboard navigability with no focus trapping.

  • Navigate the entire page using only the keyboard
  • Confirm Tab order is logical and matches visual reading order
  • Confirm arrow keys work for interactive widgets (menus, sliders, etc.)
  • Confirm focus is never trapped in a component without an escape path
  • Verify tabindex values are set correctly (prefer tabindex="0" over positive values)

Audit Definition of Done

Before closing an accessibility audit, confirm all of the following:

  • Page passes Pa11y/Koa11y against WCAG 2.2 AA and Section 508
  • Page passes initial scan with Accessibility Insights or WAVE
  • Page is fully navigable by keyboard only
  • Tab order is logical and correct
  • Arrow key navigation works as expected on interactive elements
  • A screen reader can read all meaningful content (VoiceOver on Mac, NVDA on PC)
  • Brand and site colors pass the color contrast checker (AA minimum, AAA desired)
  • JavaScript-heavy elements degrade gracefully without JS
  • Page is usable when zoomed in or out

Logging Audit Results

Log every finding with the following information:

Page Title:
Page URL:
Type of noncompliance: [Screen Reader Issue, Navigation Issue, Color Contrast Issue, etc.]
Recommendation to fix: [short synopsis of how to fix the issue]
(Optional, Internal Use Only) Hourly/point estimate to fix:

Common WordPress Accessibility Pitfalls

Block patterns and the block editor

Core blocks are generally accessible, but custom block patterns frequently introduce issues:

  • Hardcoded colors in patterns may override theme contrast settings — always use theme color tokens, not fixed hex values
  • Image blocks in patterns often ship without alt text; the pattern itself can't provide it, so ensure the editor prompt and documentation make alt text a required step for content editors
  • Decorative images (spacers, dividers, purely visual graphics) must be marked as decorative (alt="") to be skipped by screen readers

Form plugins

Contact Form 7, Gravity Forms, and similar plugins require extra attention:

  • Confirm every input has a properly associated <label> (via for/id pairing, not just visually adjacent text)
  • Inline error messages must be announced to screen readers — use aria-describedby or aria-live regions on the error container
  • Required fields must be indicated both visually and programmatically (aria-required="true" or the native required attribute)
  • Test form submission with a screen reader to confirm success/error states are communicated

Third-party embeds

Embeds sit outside your control but not outside your audit:

  • <iframe> elements must have a meaningful title attribute (e.g., title="Contact form", not title="iframe")
  • Social media embeds (Twitter/X, Instagram) frequently fail contrast and keyboard tests — if they're required, wrap them with appropriate labels and test manually
  • YouTube embeds: confirm captions are available and enabled by default where required; the YouTube iframe player is keyboard accessible but verify tab order in context

Color Contrast and Design Handoff

Accessibility is easier to fix in Figma than in code. Establish contrast expectations before a single line is written.

  • Define minimum ratios at the design token level: 4.5:1 for normal text (AA), 3:1 for large text and UI components (AA), 7:1 for normal text (AAA desired)
  • Use a Figma plugin (e.g., Contrast, Able, or A11y Annotation Kit) to check color pairs during the design review, not after
  • Flag any failing combinations before the design is approved — retrofitting contrast after development is significantly more expensive
  • When brand colors don't meet AA on white, agree on an approved dark background alternative and document both pairings in the design system
  • Interactive states (hover, focus, active, disabled) each need a passing contrast check, not just the default state

ARIA Usage Guidance

The first rule of ARIA: don't use ARIA if a native HTML element already does the job. A <button> is more accessible than a <div role="button"> because it's keyboard operable and announces correctly by default.

Use ARIA only when:

  • You're building a custom widget with no native HTML equivalent (tabs, accordions, comboboxes, modal dialogs, disclosure menus)
  • You need to expose dynamic content changes to screen readers (aria-live, aria-atomic)
  • You need to associate supplementary descriptions with an element (aria-describedby)

Common patterns:

SituationCorrect approach
Button that only has an iconaria-label="Close dialog" on the <button>
Form field with helper textaria-describedby pointing to the helper element's id
Content that updates dynamicallyaria-live="polite" on the container
Hiding decorative contentaria-hidden="true"
Labeling a landmark or regionaria-labelledby pointing to a visible heading

Never use ARIA to override semantics when the native element is correct. Using role="heading" on a <p> or role="button" on an <a> creates more problems than it solves.


Accessibility Statements and VPATs

Accessibility statement

An accessibility statement is a public-facing page (typically linked in the footer) that documents:

  • The standard the site targets (e.g., WCAG 2.2 AA)
  • Any known gaps or exceptions
  • A contact method for users to report issues or request accommodations

Government, education, and healthcare clients frequently require one. When in doubt, recommend it — it signals commitment and creates a feedback channel for real users.

VPATs

A VPAT (Voluntary Product Accessibility Template) is a formal document, published by vendors, that details how a product conforms to accessibility standards section by section. Clients in regulated industries (federal government, higher ed, healthcare) may ask for one.

VPATs are a scoped deliverable — not included in a standard engagement. If a client requests one, flag it to the PM so it can be properly estimated. Completing one requires a full audit against the relevant criteria (WCAG 2.2 A/AA, Section 508) and written documentation of each conformance level.


Owner: Mitch Canter | Last reviewed: 2026-04-30