Skip to main content

How to Make Your WordPress Site WCAG 2.2 Compliant

How to Make Your WordPress Site WCAG 2.2 Compliant

Most WordPress developers know what WCAG 2.2 requires in theory. The real challenge is translating those requirements into actual code, theme decisions, plugin choices, and editorial workflows on a live WordPress site. The principles are abstract; the implementation is specific, and the gaps between the two are where compliance failures actually live.

This guide covers the WordPress-specific implementation layer - what to do at the theme level, how to audit your plugin stack, how to handle images and forms correctly, what Gutenberg block development demands, and how to build a testing and maintenance process that keeps compliance from degrading over time.

What WCAG 2.2 Compliance Means for a WordPress Site

WCAG 2.2 introduced several new success criteria on top of the existing 2.1 requirements. The most consequential additions for WordPress developers are: Focus Appearance (2.4.11/2.4.12), which tightens rules around visible keyboard focus indicators; Dragging Movements (2.5.7), which requires single-pointer alternatives to drag interactions; Target Size (Minimum) (2.5.8), setting a 24x24 CSS pixel minimum for interactive targets; and Accessible Authentication (3.3.7/3.3.8), which affects login forms and CAPTCHA implementations.

For a WordPress site specifically, compliance is not a single decision - it is a stack of decisions made at four distinct layers: the theme, the plugins, the content, and the editorial process. A fully accessible theme can be undermined by a single poorly built plugin. Meticulous alt text strategy means nothing if your contact form lacks proper error handling. Compliance requires the whole stack to hold.

Theme-Level Requirements

Focus Indicators

WCAG 2.4.11 (Focus Appearance, AA) requires that keyboard focus indicators have a minimum area equal to the perimeter of the unfocused component multiplied by 2 CSS pixels, and a contrast ratio of at least 3:1 between focused and unfocused states. Many WordPress themes - including popular commercial themes - still suppress focus outlines entirely with outline: none or outline: 0 in their base stylesheets. This is a direct WCAG failure and, critically, it is invisible during mouse-based QA.

The fix is to replace suppressed outlines with a deliberate focus style. A reliable pattern uses :focus-visible rather than :focus, so the indicator appears for keyboard users but not on mouse click - which addresses the common objection that focus rings look "ugly" during normal browsing:

*:focus-visible {
  outline: 3px solid #005fcc;
  outline-offset: 2px;
}

Test every interactive element - links, buttons, form fields, custom dropdowns, modal triggers - to confirm the indicator is visible and meets contrast requirements.

Contrast Ratios

WCAG 1.4.3 requires a 4.5:1 contrast ratio for normal text and 3:1 for large text (18pt or 14pt bold). WordPress themes frequently fail this on secondary text, placeholder text, disabled state labels, and footer copy. Use a tool like the Color Converter to inspect hex values, then verify contrast ratios against the WCAG formula. Pay particular attention to text rendered over images or gradient backgrounds - those ratios shift dynamically and need to be verified at the worst-case overlay point.

Keyboard Navigation and Skip Links

Every WordPress theme should include a skip-to-main-content link as the first focusable element in the DOM. Many themes include this but hide it visually and fail to make it visible on focus - which satisfies neither sighted keyboard users nor automated auditors. The correct implementation renders the link off-screen by default and brings it into view on :focus:

.skip-link {
  position: absolute;
  left: -9999px;
}
.skip-link:focus {
  left: 0;
  top: 0;
  z-index: 9999;
}

Beyond skip links, test tab order throughout the theme. Sticky headers, mega menus, and off-canvas navigation patterns frequently create keyboard traps or illogical tab sequences that break WCAG 2.1.1 and 2.1.2.

The Plugin Landscape

Plugins are the most unpredictable accessibility variable in any WordPress stack. Common offenders include:

  • Popup and modal plugins that fail to trap focus within the open modal, allowing keyboard users to interact with content behind it. Any modal must implement a focus trap on open and return focus to the trigger element on close.

  • Slider and carousel plugins that auto-advance content without pause controls, violating WCAG 2.2.2 (Pause, Stop, Hide). If auto-play cannot be disabled, the plugin is not compliant.

  • Cookie consent plugins that render consent dialogs without proper ARIA roles, focus management, or keyboard dismissal. Many popular consent banners fail 2.1.1 outright.

  • Table plugins that generate complex data tables without <th> scope attributes or caption elements, making the data inaccessible to screen reader users.

  • Social sharing plugins that render icon-only buttons without accessible names - a direct failure of WCAG 4.1.2.

The practical approach: audit each plugin's output in the DOM, not just its settings panel. Run axe DevTools on every page type where a plugin renders output. If a plugin cannot be made compliant through configuration, it needs to be replaced or its output needs to be overridden via a child theme or custom filter.

Images: Alt Text Strategy

WCAG 1.1.1 requires a text alternative for every non-text content item. In WordPress, this means every image needs a deliberate alt text decision - not just a filled field.

The core distinction is between informative and decorative images. An informative image conveys content or function that is not present in surrounding text. It needs descriptive alt text that communicates its meaning. A decorative image adds visual interest but provides no information not already conveyed by adjacent text. It should have an empty alt attribute (alt="") so screen readers skip it entirely - not a filename, not "image", not a repetition of the caption.

WordPress's media library makes this easy to get wrong. When you upload an image and leave the alt field blank, WordPress outputs no alt attribute at all in some contexts - which screen readers handle by reading the filename. Always set alt text explicitly in the media library or at the block level in Gutenberg. For images used purely as backgrounds via CSS, no alt attribute is needed since they are not in the DOM as <img> elements.

For complex images like charts or infographics, a short alt text is insufficient. WCAG 1.1.1 allows for a longer description via aria-describedby pointing to a visible caption, or via a linked long description. Neither approach is natively supported in core Gutenberg blocks, so custom block development or a wrapper pattern is typically required.

Forms: Labels, Errors, and Autocomplete

WordPress forms - whether built with Contact Form 7, Gravity Forms, WPForms, or custom code - have consistent accessibility failure patterns.

Labels must be programmatically associated with their inputs using a for attribute matching the input's id. Placeholder text is not a label substitute - it disappears on input and has insufficient contrast in most browsers. Every input, select, and textarea needs a persistent, visible label.

Error messages must be specific, identify the field in error, and be programmatically associated with that field. WCAG 3.3.1 requires that input errors are identified and described in text. Injecting a generic "Please check your form" message at the top of the page does not satisfy this. Each error message should be linked to its field via aria-describedby, and the error should be announced to screen readers via an aria-live region or by moving focus to the first error field.

Autocomplete attributes are required by WCAG 1.3.5 (Identify Input Purpose) for inputs that collect personal data. Name, email, phone, address, and payment fields must carry the appropriate autocomplete value (name, email, tel, street-address, etc.). Most form plugins do not add these by default - you will need to add them via plugin settings, custom field configurations, or filter hooks.

For login forms specifically, WCAG 3.3.8 (Accessible Authentication, AA) prohibits cognitive function tests unless an alternative is provided. This directly affects CAPTCHA implementations: image-based CAPTCHAs that require identifying objects are non-compliant unless an audio alternative or other mechanism is available. Google reCAPTCHA v3 (invisible, score-based) is generally the least problematic option from a WCAG perspective.

Gutenberg Blocks and Custom Block Development

Core Gutenberg blocks have improved significantly in accessibility, but custom block development introduces risk at every step. Key requirements for any custom block:

  • Semantic HTML output: Use the correct element for the job. A block that renders a button as a <div> with a click handler is not keyboard accessible and has no implicit ARIA role. Use <button> for actions and <a> for navigation.

  • ARIA roles and properties: When a custom block implements a widget pattern (tabs, accordion, disclosure), it must follow the ARIA Authoring Practices Guide for that pattern - including keyboard interaction models (arrow key navigation for tab panels, Enter/Space for disclosure buttons).

  • Block editor accessibility: The editing experience in the block editor also needs to be accessible. Use the useBlockProps hook correctly and ensure any custom toolbar controls have accessible labels via the label prop on ToolbarButton.

  • Color controls: If your block exposes color pickers to editors, enforce contrast ratio validation. Editors should not be able to select a foreground/background combination that fails WCAG 1.4.3 - consider adding a contrast warning in the block's inspector controls.

Testing: Automated and Manual

Automated tools catch roughly 30-40% of WCAG failures. They are necessary but not sufficient. A complete testing process uses both layers.

Automated Testing

Run axe DevTools (browser extension or integrated via Cypress/Playwright) and Lighthouse accessibility audit on every distinct page template - not just the homepage. Each page type (archive, single post, WooCommerce product, search results, 404) can have unique failures. Integrate axe into your CI pipeline so accessibility regressions are caught before deployment, not after. The SEO Analyzer also surfaces accessibility-adjacent issues like missing alt text and structural problems that affect both accessibility and search performance.

Manual Testing

Keyboard-only navigation testing means putting the mouse away entirely and navigating the entire site using only Tab, Shift+Tab, Enter, Space, and arrow keys. Verify that: all interactive elements are reachable, focus order is logical, no keyboard traps exist, modals and dropdowns open and close correctly, and the skip link functions.

Screen reader testing should cover at minimum NVDA with Firefox (Windows) and VoiceOver with Safari (macOS/iOS). Test heading structure, landmark navigation, form interaction, image alt text announcement, and dynamic content updates. Screen reader behavior differs enough between combinations that testing only one pairing will miss real failures.

Staying Compliant Over Time

Accessibility compliance degrades. Every plugin update, theme change, and new piece of content is an opportunity for regression. The sites that maintain compliance are the ones that treat it as a workflow property, not a one-time audit.

Content editor training is non-negotiable. Editors need to understand: how to write meaningful alt text, why heading levels are structural rather than stylistic, how to create accessible links (no "click here"), and why pasting rich text from Word or Google Docs can introduce inaccessible markup. A one-page editorial accessibility guide, pinned in your team's documentation, handles most of this.

Build accessibility into the publishing workflow. Before any post or page goes live, a checklist item for alt text, heading structure, and link text takes under two minutes. WordPress plugins like WP Accessibility or custom admin notices can surface reminders within the editor interface itself.

Schedule periodic audits - at minimum after major theme updates, plugin updates to key plugins (forms, popups, sliders), and after any redesign. Automated scans can be scheduled via CI or a monitoring service. Manual keyboard testing should accompany any significant front-end change.

WCAG 2.2 compliance on WordPress is achievable for any site when implementation is treated as an engineering concern - addressed in code, tested systematically, and maintained through process rather than periodic scrambles. The sites that fail are not the ones that lack knowledge; they are the ones that defer the work until it becomes a legal or contractual obligation rather than a technical standard.

Get in touch

Have questions about this article?

Get in touch if you'd like to learn more about this topic.

Contact us