“Accessible” is a word a theme can earn or merely claim. A theme directory badge, a green automated score and a line on a sales page are three different things, and none of them tells a keyboard user whether they can finish a checkout. This checklist is for theme authors and agencies who want to make the claim honestly: what to test, how to test it, what each failure usually looks like in a block theme, and the code that fixes it.

We stay close to two primary sources, both read on 23 October 2026: the WordPress.org Theme Review Team’s accessibility-ready requirements, and the W3C’s pages for WCAG 2.2. Where a point comes from our own experience of building block themes and not from those sources, we say it is our advice. We did not run every snippet below in a shipping theme for this article. Treat the code as a starting point you test in your own theme.

The short answer

  • The WordPress.org accessibility-ready tag is a minimum. The handbook says the tag means a theme meets the review team’s minimum standards, and that it does not mean the theme meets WCAG AA.
  • WCAG 2.2 added nine success criteria and removed one (4.1.1 Parsing). Six of the nine are level A or AA, and those are the ones to test.
  • Automated tools find part of the problems. A keyboard, a zoom setting and a screen reader find the rest. Plan an hour per template.
  • Say what you tested. “Tested against WCAG 2.2 AA on [date], with [tools]” is a claim you can defend. “Fully accessible” is not.

What the accessibility-ready tag requires

The Theme Review Team’s handbook explains how the tag works. A theme author adds the tag before submitting a new theme, and tagged themes get an accessibility review during initial approval and may not go live in the directory until they pass an audit. A live theme can request a review from its author’s WordPress.org account, and must not add the tag without approval, because that can lead to suspension. Tagged themes may be re-reviewed at any time, and updates go to an accessibility queue.

The handbook lists 18 required items. We list the titles here, because they make a useful skeleton for your own checklist:

  1. Skip to Content Link
  2. Meaningful landmark roles and names
  3. Keyboard navigation support
  4. Controls with accessible names, roles, and states
  5. Labelled form fields
  6. Headings with meaningful structure
  7. Underlined links in text
  8. No ambiguous link text
  9. Sufficient color contrast of text and UI controls
  10. Alternative text on images and graphics
  11. Accessible audio, video, and animations
  12. Support for reflow, resize, and text spacing changes
  13. No unexpected changes of context
  14. No links opening new windows or tabs without warning
  15. Content on hover or focus is accessible
  16. Accessibility statement
  17. Must not recommend or require inaccessible plugins
  18. Screen reader text supported

The handbook points to the full rule text at wpaccessibility.org, in its theme guidelines. We only read the list of titles, so read the guideline for each item before you claim it.

One line from the handbook deserves repeating: the requirements are minimums, and authors are encouraged to exceed them. Treat the tag as the floor.

What WCAG 2.2 added

The W3C’s “What’s new in WCAG 2.2” page lists nine new success criteria:

CriterionLevelPlain meaning
2.4.11 Focus Not Obscured (Minimum)AAA focused item must not be entirely hidden by other content you created.
2.4.12 Focus Not Obscured (Enhanced)AAANo part of a focused item may be hidden.
2.4.13 Focus AppearanceAAAThe focus indicator is large and contrasting enough to see.
2.5.7 Dragging MovementsAAAnything that needs dragging has a single-pointer alternative.
2.5.8 Target Size (Minimum)AAPointer targets are at least 24 by 24 CSS pixels, or spaced apart.
3.2.6 Consistent HelpARepeated help options stay in the same relative order.
3.3.7 Redundant EntryADo not make people re-enter information they already gave in the same process.
3.3.8 Accessible Authentication (Minimum)AANo memory, puzzle or transcription test to log in, unless there is an alternative or help.
3.3.9 Accessible Authentication (Enhanced)AAAA stricter version with no cognitive tests such as object recognition.

The page also says 4.1.1 Parsing is obsolete and removed in WCAG 2.2. For a theme, the practical consequence is that you no longer need to chase a validator for duplicate attributes as an accessibility requirement, though valid markup is still good practice.

A theme controls some of these directly (focus, target size, contrast, layout) and others only partly (authentication and forms are often plugin territory). For the ones that belong to plugins, say so in your accessibility statement and test the most common plugins with your theme.

The checklist, with code and tests

We go in the order a keyboard user meets things on a page: first the skip link and landmarks, then focus, then targets, then colour and text, then content and forms, then the things that move.

What to check: press Tab once on a fresh page load. A “Skip to content” link should appear, and activating it should move focus to the main content. Then check that the page has one header, one main and one footer landmark, and that repeated landmarks, such as two navigation areas, have different labels.

In a block theme: WordPress adds a skip link to block themes, so the job is to make sure it lands somewhere real. That means every template must contain exactly one main element. Set the tag on the group block that wraps your post content, and set the tags on your template parts:

<!-- wp:template-part {"slug":"header","tagName":"header"} /-->

<!-- wp:group {"tagName":"main","layout":{"type":"constrained"}} -->
<main class="wp-block-group">
  <!-- wp:post-content /-->
</main>
<!-- /wp:group -->

<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->

Common failure: a template, usually a custom landing page, with no main, or with main twice because a pattern added one inside the template’s own wrapper. Search your templates and patterns for "tagName":"main" and count them per template.

2. Keyboard navigation and visible focus

What to check: unplug the mouse. Move through the whole page with Tab and Shift+Tab, open the menu, use the search, submit a form. Can you reach everything? Can you always see where you are? Does the order make sense?

The fix for invisible focus is a single rule in your stylesheet. Use :focus-visible, so mouse users do not see rings after clicks but keyboard users always do:

:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--wp--preset--color--contrast);
  outline-offset: 2px;
}

The outline colour has to contrast with whatever it sits on, in both the light and any dark style. If your theme ships style variations with different backgrounds, test the ring in each. The enhanced criterion 2.4.13 sets a stricter bar for size and contrast at level AAA, and it is a good target if you can reach it cheaply.

Common failure: a reset stylesheet or a design tool’s export that sets outline: none on buttons and links. Search your CSS for outline: none and outline: 0, and for each hit ask what replaces it.

3. Focus not obscured: sticky headers

This is new in WCAG 2.2, at level AA (criterion 2.4.11). The requirement text says a focused component must not be entirely hidden due to author-created content. The classic way to fail it in a theme is a sticky header: tab down a long page and the focused link slides under the header.

What to check: with a sticky or fixed header on, tab through a page with many links and watch whether the focused item ever disappears behind it, or behind a cookie banner or a chat widget.

The fix is to reserve scroll space equal to the header height, so the browser scrolls focused items clear of it:

html {
  scroll-padding-block-start: var(--theme-header-height, 5rem);
}

.site-header--sticky {
  position: sticky;
  inset-block-start: 0;
}

Set the custom property to the real height of your header, and update it for the mobile header, which is often a different height. Use the logical property scroll-padding-block-start so the rule survives writing-mode changes, as we explain in our guide to block theme CSS that survives RTL.

4. Target size

Criterion 2.5.8 (level AA) says the size of the target for pointer inputs is at least 24 by 24 CSS pixels, with five exceptions: spacing (undersized targets placed so that 24 pixel circles centred on each do not overlap another target), an equivalent control on the same page, inline targets in a sentence, controls sized by the browser and not modified by the author, and cases where the presentation is essential.

What to check: small icon buttons are the usual offenders: the close button on a modal, the social icons in the footer, pagination dots, quantity steppers. Measure them in the browser’s inspector.

The fix is a minimum size on controls. You can set button padding in theme.json and keep the icon-only controls above the minimum in CSS:

{
  "styles": {
    "elements": {
      "button": {
        "spacing": {
          "padding": {
            "top": "0.75rem",
            "bottom": "0.75rem",
            "left": "1.25rem",
            "right": "1.25rem"
          }
        }
      }
    }
  }
}
.wp-block-social-links .wp-social-link a.wp-block-navigation__responsive-container-close {
  min-inline-size: 24px;
  min-block-size: 24px;
}

Twenty-four pixels is the minimum, not a good design target. Larger targets are easier for everyone, and many design systems aim for 44 pixels, which is the level AAA size in a different criterion. Our design system examples article shows how larger systems document this as a token.

5. Colour contrast

WCAG’s contrast criterion (1.4.3, level AA) requires at least 4.5:1 for normal text and at least 3:1 for large text, where large means at least 18 point, or 14 point bold. The W3C’s page notes that ratios are not rounded: 4.499:1 fails 4.5:1. Interface components and graphics are covered by 1.4.11, for which 3:1 is the benchmark.

What to check: every text and background pair you define in theme.json, in every style variation, including hover and disabled states, placeholders, text over images, and the colours users can pick in the editor.

A practical method: list the palette as roles and test the pairs, not the individual colours.

{
  "settings": {
    "color": {
      "palette": [
        { "slug": "base", "name": "Base", "color": "#ffffff" },
        { "slug": "contrast", "name": "Contrast", "color": "#111827" },
        { "slug": "accent", "name": "Accent", "color": "#1d4ed8" }
      ]
    }
  }
}

Then test contrast on base, accent on base (for links), and base on accent (for buttons). Use a contrast checker and record the ratios in a table you keep with the theme. When a colour comes from a customer’s brand, the risk is highest: we describe one way to derive readable text automatically in 7 of 11 Themes Failed Contrast, and a way to share one palette between a CSS framework and theme.json in From a Tailwind Theme to theme.json.

The handbook requires underlined links in text, and no ambiguous link text. Colour alone should not mark a link. In theme.json, you can set the underline for the link element:

{
  "styles": {
    "elements": {
      "link": {
        "typography": { "textDecoration": "underline" }
      }
    }
  }
}

Navigation menus and buttons are different from links in running text, and you can remove the underline there as long as other cues remain. For ambiguous link text, search your patterns for “Read more” and “Click here”. A link that says only “Read more” is read out of context by a screen reader’s link list. Core’s Read More block can take custom text that includes the post title, and a visually hidden suffix works in a pattern.

7. Headings and structure

What to check: use a headings list in a screen reader or a browser extension, and read it as an outline. There should be one h1 per page, usually the page or post title, and levels should not skip.

The block theme trap: headings in patterns. A pattern author picks a heading level for how it looks, and the page ends up with an h4 directly under an h1. Set the heading level for the pattern’s role and style the size with a block style or a font-size preset instead. A heading’s level is structure, and its size is style.

8. Forms and controls

Every field needs a label that is programmatically tied to it, and every control needs an accessible name, role and state. Core’s search and comment blocks supply labels. The risks are in custom patterns and in any form plugin. Check that placeholders are not the only label, that error messages are announced and linked to their fields, and that required fields are marked in text and not only in colour.

For styling forms in theme.json, see form styling in theme.json. Make sure the border that marks a field has at least 3:1 contrast against the page.

9. Reflow, zoom and text spacing

What to check: zoom the browser to 200 percent and then to 400 percent on a desktop viewport. The page should reflow into a single column with no horizontal scroll for text content, and nothing should be cut off or overlap. Then apply a text spacing bookmarklet, or the equivalent override, to make line height, paragraph spacing and letter spacing larger, and check that nothing is clipped.

Common failures: fixed heights on cards and hero sections, text in containers with overflow: hidden, and font sizes set in pixels in custom CSS. Use rem, clamp() through theme.json fluid typography, and min-block-size instead of block-size for anything that contains text.

10. Motion, hover and focus content

Anything that animates should respect the user’s system setting for reduced motion:

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }
}

For content that appears on hover or focus, such as a mega menu or a tooltip, the handbook requires it to be accessible. Check that it can be reached by keyboard, that it stays visible while the pointer or focus is on it, and that it can be dismissed with Escape. If you build popovers, our article on popovers without JavaScript in block themes shows how native behaviour handles dismissal and focus for you.

The handbook requires no links opening new windows or tabs without warning, and no unexpected changes of context. Search your templates for target="_blank". Where it is needed, say so in the link text or with visually hidden text. And check that choosing an option in a select or ticking a box does not submit a form or move the page on its own.

12. Images, audio and video

Images need alternative text, or an empty alt when decorative. Check the theme’s own images, such as logos, icons and decorative patterns, because the theme author controls those. Video needs captions, audio needs transcripts, and autoplay with sound should not happen. The handbook lists accessible audio, video and animations as a required item.

13. Drag and authentication

Two of the new criteria rarely apply to a theme alone, but they apply to what you ship. For dragging (2.5.7, level AA), check any slider, carousel or sortable list that needs a drag, and provide buttons as an alternative. For authentication (3.3.8, level AA), check any login form your theme styles: allow paste and password managers, and do not add a puzzle or a transcription test without an alternative. These are common in plugins, so test with the login and checkout plugins your customers use most.

14. Consistent help and redundant entry

For consistent help (3.2.6, level A), if your theme shows a help link or a contact option on many pages, keep it in the same place in the same order. A footer or header pattern that does this by design passes by default. For redundant entry (3.3.7, level A), check multi-step forms and checkouts, which are usually plugin territory, and note in your statement which plugins you tested.

How to test: a one-hour routine per template

  1. Automated pass (10 minutes). Run a browser accessibility checker on the template. Fix everything it flags. Remember that an automated tool finds only a part of the problems, and passing it proves little.
  2. Keyboard pass (10 minutes). No mouse. Skip link, menu, search, form, footer. Check focus is always visible and never hidden by a sticky element.
  3. Zoom pass (10 minutes). 200 percent and 400 percent, then increased text spacing.
  4. Screen reader pass (20 minutes). Use the screen reader you have access to: VoiceOver on a Mac, NVDA on Windows. Listen to the landmarks list, the headings list and the links list. Does the page make sense when heard?
  5. Contrast and target pass (10 minutes). Check your palette pairs, focus rings, borders and icon buttons against the numbers above.

Do this for each distinct template and each style variation: home, archive, single post, page, search, 404, and any custom layouts. Record the date, the tools and the result for each.

What to publish: the accessibility statement

The handbook lists an accessibility statement as a required item. Write one that says what you tested and how. Include the standard (WCAG 2.2 AA), the date, the browsers and assistive technology, the templates covered, known gaps, and a way to report a problem. Known gaps are not a weakness: they are what makes the rest believable. A statement that claims perfection is a signal that nobody tested.

Accessibility statement

We aim to meet WCAG 2.2 level AA. We last tested this theme on
[date] with [browser] and [screen reader], on these templates:
[list].

Known gaps: [list, or "none found in testing"].

Plugins we tested with: [list]. We cannot speak for plugins
not listed.

To report a problem, write to [address]. We reply within
[number] working days.

Common questions

Is a theme with the accessibility-ready tag WCAG AA compliant?

Not by that fact alone. The handbook says the tag means the theme reaches the minimum standards the review team has set, not that it meets WCAG AA.

Do WCAG 2.2 changes apply to themes?

Several do directly: focus not obscured, target size and, through the content you ship, dragging. Others depend on plugins, such as authentication and redundant entry. Test both.

Can I rely on an automated score?

No. Use it to catch the easy faults and to guard against regressions, and use the manual routine above for the rest.

How often should I retest?

After every release that changes templates, patterns, colours or JavaScript, and after major WordPress or plugin updates. The handbook notes that tagged themes may be re-reviewed at any time, which is a reason not to let the claim go stale.

What about the editor?

Your theme’s editor styles should match the front end, so authors see focus rings and contrast as visitors do. Test in the editor too.

The complete path: build the checks into the theme, not around it

A checklist you run once is a report. A checklist built into how the theme is made is a standard. Here is the whole path we would follow in a block theme, from the first commit to a release you can describe honestly.

1. Put the decisions in theme.json

Palette roles, the underline on links, button padding and the focus colour are decisions, so they belong in one file that the editor and the front end both read. When the palette changes, the contrast table you keep with the theme changes in the same commit.

2. Ship the focus, target and scroll rules in the base stylesheet

The :focus-visible rule, the scroll-padding-block-start value for a sticky header, the minimum size for icon controls and the reduced-motion block above go in the base stylesheet, once, and every template inherits them. Patterns then cannot forget them.

3. Make patterns carry the structure

Give every pattern the right heading level for its role, one main per template, and link text that makes sense out of context. A pattern is where most accessibility regressions arrive, because it is copied into pages by people who do not see the markup.

4. Turn the routine into a release gate

  1. Run an automated check on every template in CI, and fail the build on new errors.
  2. Keep the one-hour manual routine as a release step, and record the date, tools and result in the repository next to the accessibility statement.
  3. Re-run it after every change to templates, patterns, colours or scripts, and after WordPress major releases.

5. Publish what you tested

Put the statement from the previous section on the theme’s page and in the repository, with the date and the known gaps. When a gap is fixed, change the date, not just the line.

Where our own work fits

Brndle is a free, open-source WordPress theme from Wbcom Designs, and its site describes itself as the home of a single readability and accessibility standard that themes should meet on any runtime. We are not claiming that the Brndle theme itself passes the checklist above, and its page does not make that claim for each item. If you want a theme or a set of block patterns built to a standard like this one, or an existing theme brought up to it and retested, Wbcom Designs takes that on as project work. Its project page describes engagements from one-month sprints to year-long retainers, and it starts with a conversation at wbcomdesigns.com/start-a-project.

The takeaway

Before you call a theme accessible, run the routine on every template, fix what fails, write down what you tested and publish the gaps you know about. Use the handbook’s 18 items as your floor and the WCAG 2.2 additions as your edge: focus not obscured and target size are the two a theme can most easily get wrong. Retest after every release.

Sources, read on 23 October 2026