Wp accessibility audit
Skill Lonsdale201/wp-agent-skills/wordpress/wp-accessibility-audit
A community-maintained collection of agent skills for WordPress plugin and theme development.
npx -y skills add Lonsdale201/wp-agent-skills --skill wp-accessibility-auditAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Audit or implement accessibility for WordPress plugins, admin screens, frontend plugin output, and classic themes against WCAG 2.2 A/AA and WordPress accessibility patterns. Use when the user asks for akadalymentesites/accessibility/a11y, form field labels, `aria-label`, `aria-describedby`, keyboard navigation, focus states, admin notices, live AJAX updates, modal/dialog UI, color contrast, font sizing, reduced motion, target size, screen-reader text, image alt text, or making a plugin/theme usable without a mouse or screen.
SKILL.md
12.5 KB, as published. Nobody here has run it
WordPress Accessibility Audit
Use this when making a WordPress plugin, admin page, frontend feature, or classic theme accessible. The target baseline is WCAG 2.2 Level A and AA, matching WordPress' stated accessibility commitment. AAA is encouraged where practical, but do not claim full AAA unless every relevant AAA criterion has been audited.
This skill is not a legal certification. It is an implementation and review checklist for code.
When to Use This Skill
- The task says accessibility, a11y, WCAG, screen reader, keyboard, akadalymentesites, ARIA, or accessible forms.
- Reviewing admin screens, settings pages, metaboxes, list tables, media frames, custom dialogs, AJAX UI, or frontend shortcode output.
- Adding labels/help text/errors for fields.
- Fixing color contrast, focus visibility, target sizes, font sizing, reduced motion, or hover-only interactions.
- Making live updates announce through
wp.a11y.speak().
Baseline Rules
- Content and controls are usable with keyboard only.
- Every interactive element has a correct native role or ARIA role.
- Every form control has an accessible name.
- Focus is visible and not hidden behind sticky headers/toolbars.
- Text and UI contrast meet WCAG AA.
- Text can be zoomed to 200% without loss of content or functionality.
- Motion-heavy UI respects reduced-motion preferences.
- Errors are visible, understandable, and programmatically associated with fields.
- Dynamic updates are announced when they change user-relevant state.
- Automated tests are supplemented by keyboard and screen-reader checks.
ARIA Decision Rule
Prefer native HTML first. ARIA patches semantics; it does not make broken interaction accessible by itself.
Use this order:
- Correct native element:
<button>,<a>,<label>,<input>,<select>,<textarea>,<fieldset>,<legend>,<dialog>,<nav>,<main>. - Visible text labels.
aria-labelledbywhen visible text elsewhere labels the control.aria-labelonly when no visible label is possible, usually icon-only buttons or named landmarks.aria-describedbyfor help text, constraints, and errors. It is not the field's name.
Do not add ARIA roles that duplicate or contradict native semantics.
Form Fields
Every input/select/textarea needs a real accessible name.
Good visible label:
<label for="myplugin_api_key"><?php esc_html_e( 'API key', 'textdomain' ); ?></label>
<input
type="text"
id="myplugin_api_key"
name="myplugin_options[api_key]"
value="<?php echo esc_attr( $api_key ); ?>"
aria-describedby="myplugin_api_key_help"
>
<p id="myplugin_api_key_help" class="description">
<?php esc_html_e( 'Create this key in your provider dashboard.', 'textdomain' ); ?>
</p>
- Do not use placeholder text as the only label.
- Do not use
aria-labelwhen a visible<label>can exist. - Keep
forandidexactly paired. - Use
aria-describedbyfor help text and constraints. - For required fields, use native
requiredwhere validation supports it, plus visible required text where needed. - For invalid fields, set
aria-invalid="true"and connect the error witharia-describedby. - Radio/checkbox groups need
<fieldset>and<legend>.
Error example:
<label for="myplugin_email"><?php esc_html_e( 'Notification email', 'textdomain' ); ?></label>
<input
type="email"
id="myplugin_email"
name="myplugin_email"
value="<?php echo esc_attr( $email ); ?>"
aria-describedby="myplugin_email_help myplugin_email_error"
aria-invalid="true"
>
<p id="myplugin_email_help" class="description"><?php esc_html_e( 'Used for failure alerts.', 'textdomain' ); ?></p>
<p id="myplugin_email_error" class="notice notice-error inline">
<?php esc_html_e( 'Enter a valid email address.', 'textdomain' ); ?>
</p>
Buttons, Links, Icons
- Use
<button type="button">for actions that change UI state. - Use
<a href="...">for navigation. - Never use
<a href="#">or clickable<div>for buttons. - Icon-only buttons need visible text,
.screen-reader-text, oraria-label. - Decorative icons inside named controls should use
aria-hidden="true"and not receive focus. - Repeated links like "Read more" need extra context through visible text or
.screen-reader-text.
Icon button:
<button type="button" class="button myplugin-refresh">
<span class="dashicons dashicons-update" aria-hidden="true"></span>
<span class="screen-reader-text"><?php esc_html_e( 'Refresh import status', 'textdomain' ); ?></span>
</button>
Keyboard and Focus
-
Tab reaches every interactive element in a logical order.
-
Shift+Tab works backward.
-
Enter activates links and submit buttons.
-
Space activates buttons, checkboxes, and toggles.
-
Escape closes modals, popovers, and autocomplete popups.
-
Arrow-key behavior is implemented for custom menu/listbox/tab/slider patterns only when the ARIA APG pattern requires it.
-
Do not use positive
tabindex. -
Use
tabindex="-1"only for programmatic focus targets such as error summaries or modal containers. -
Never remove outlines without a visible replacement.
-
After AJAX save/delete/filter operations, keep focus stable or move it deliberately to the next useful place.
-
Do not trap focus except in true modal dialogs.
-
When closing a modal, return focus to the control that opened it.
Focus CSS:
.myplugin-ui :focus-visible {
outline: 2px solid #1d2327;
outline-offset: 2px;
}
@media (forced-colors: active) {
.myplugin-ui :focus-visible {
outline: 2px solid CanvasText;
}
}
Dynamic Updates and Notices
For admin JavaScript that updates state without a full page load, enqueue wp-a11y and announce meaningful changes.
wp_enqueue_script(
'myplugin-admin',
plugins_url( 'assets/admin.js', __FILE__ ),
array( 'wp-a11y', 'wp-i18n' ),
'1.0.0',
true
);
const { __ } = wp.i18n;
wp.a11y.speak( __( 'Settings saved.', 'textdomain' ) );
- Announce results, not implementation details.
- Use
politeannouncements for normal updates andassertiveonly for urgent errors. - Visible notices still matter; screen-reader announcements do not replace visible feedback.
- Error summaries should be focusable with
tabindex="-1"and focused after failed validation.
Color, Text, and Layout
-
Normal text contrast: at least 4.5:1.
-
Large text contrast: at least 3:1.
-
UI components and graphical state indicators: at least 3:1.
-
Do not use color as the only way to show errors, selected state, required fields, or links in prose.
-
Use relative units for text:
rem,em,%. -
As design guidance, start body text at
1rem, avoid UI text below 14px, and prefer 16px for content/form-heavy screens. WCAG does not define a universal minimum font-size pass/fail threshold. -
Use line-height around
1.4to1.6for readable body text. -
Avoid fixed-height containers for text that can wrap or zoom.
-
Test text zoom at 200%, and test reflow at 400% zoom / a 320 CSS-pixel-wide viewport without two-dimensional scrolling except for allowed content such as data tables.
-
Test WCAG text-spacing overrides: line height
1.5, paragraph spacing2em, letter spacing0.12em, and word spacing0.16em; content and controls must remain available.
Reduced motion:
@media (prefers-reduced-motion: reduce) {
.myplugin-nonessential-animation {
scroll-behavior: auto !important;
animation: none !important;
transition: none !important;
}
}
Scope reduced-motion changes to nonessential effects. Do not globally shorten
animations when application logic waits for animationend/transitionend;
provide a no-motion code path and test that completion still occurs.
- WCAG 2.2 AA target size is 24 by 24 CSS pixels, with defined exceptions for sufficient spacing, inline text, equivalent larger controls, user-agent controls, and essential presentation. Audit the exception before reporting every smaller compact control as a failure.
- Prefer 44 by 44 CSS pixels for touch-heavy frontend UI.
- If the visual icon is smaller, increase clickable padding.
Landmarks, Headings, and Tables
- Use one meaningful
h1for the screen/admin page title. - Keep headings in logical order; do not choose heading levels by visual size.
- Admin pages should use the normal
.wrap > h1pattern. - Use landmarks for major areas:
main,nav,aside,header,footer. - Multiple
navlandmarks need names witharia-labeloraria-labelledby. - Data tables need header cells with
scope="col"orscope="row". - Do not use tables for layout.
Media and Images
- Informative images need meaningful alt text.
- Decorative images use empty
alt="". - Do not repeat adjacent text in alt text.
- SVG icons that are decorative use
aria-hidden="true" focusable="false". - Audio/video must not autoplay with sound.
- Captions/transcripts are required when media conveys information.
Custom Components
Before building a custom widget, check whether native HTML or a WordPress component already solves it.
-
Use the WAI-ARIA APG pattern for the component type.
-
Implement the documented keyboard interaction.
-
Manage focus deliberately.
-
Keep ARIA state synchronized:
aria-expanded,aria-selected,aria-checked,aria-disabled,aria-controls. -
Test with keyboard and at least one screen reader.
-
Modal dialogs.
-
Autocomplete/listbox.
-
Tabs.
-
Accordions/disclosures.
-
Drag-and-drop UIs.
-
Toasts/live updates.
-
Date pickers.
Audit Workflow
- Identify every interactive element.
- Verify accessible name, role, value, and state.
- Tab through the whole UI without a mouse.
- Trigger validation errors and verify visible/focus/ARIA behavior.
- Test 200% text zoom, 400%/320-CSS-pixel reflow, and text-spacing overrides.
- Check contrast for text, focus, borders, icons, and error states.
- Disable animations through reduced-motion preference.
- Run an automated checker, then manually verify anything it cannot know.
- Record issues with severity and WCAG/WordPress rationale.
Severity Guide
- Critical: keyboard trap, unreachable primary action, missing accessible names on required controls, modal focus broken, security/checkout/account flow unusable.
- High: invalid fields not announced, focus invisible, insufficient contrast on important text/actions, destructive action ambiguity, dynamic state not announced.
- Medium: poor heading order, missing landmark names, weak help text association, target size below 24px without a WCAG exception, or nonessential motion not reduced.
- Low: redundant labels, minor screen-reader verbosity, cosmetic focus inconsistency that remains usable.
Common Mistakes
- Common failures: replacing visible labels with
aria-label, usingaria-describedbyas the name, hiding labels withdisplay:none, removing outlines, positivetabindex, click handlers on non-interactive elements, color-only state, silent AJAX completion, and trusting an automated scan as proof of accessibility.
Cross-References
- Pair with
wp-admin-settings-api,wp-admin-list-table, orwp-admin-media-framefor those specific admin components. - Use
classic-theme-accessibility-semanticsfor classic theme document structure and landmarks.
References
- Official documentation: https://developer.wordpress.org/coding-standards/wordpress-coding-standards/accessibility/
- Official documentation: https://www.w3.org/TR/WCAG22/
- Official documentation: https://www.w3.org/WAI/ARIA/apg/
- Official documentation: https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/
- Official documentation: https://www.section508.gov/develop/guide-accessible-web-design-development/
- Verified source paths:
wp-admin/css/common.csswp-includes/js/dist/a11y.jswp-includes/script-loader.phpwp-includes/comment-template.phpwp-includes/media-template.phpwp-includes/class-wp-customize-control.phpwp-admin/js/common.js