Accessibility Audit (WCAG 2.2)
Every form has a built-in accessibility audit that checks the markup for WCAG 2.1/2.2 issues affecting screen reader and keyboard users. The audit is a static analysis of the form's HTML -- it runs locally with no network calls and is cheap enough to run on every save.
Class: Core_Forms\Admin\AccessibilityTester
Source: src/admin/class-accessibility-tester.php
The Audit Panel
Open a form and switch to the Fields tab. The WCAG 2.2 audit panel sits above the builder and shows:
- A summary line ("No automated issues found." or "N issues found.").
- The first 10 issues, each with a rule code and a plain-language message.
- Run audit -- re-checks the current saved markup on demand.
- Fix safe issues -- applies automatic repairs (disabled when there are no issues).
The audit also runs automatically whenever the form is saved (visual builder, code editor, or REST), and the result is cached in the _cf_a11y_report post meta. The forms list screen shows a per-form Accessibility column based on the same report.
What the Audit Checks
| Rule | What it flags |
|---|---|
missing_label |
A control with no <label for>, wrapping <label>, aria-label, or aria-labelledby |
group_no_fieldset |
Radio/checkbox groups (2+ inputs sharing a name) not wrapped in a <fieldset> with a <legend> |
missing_aria_required |
Required fields missing aria-required="true" (reported when 3 or more) |
select_no_placeholder |
A required <select> whose first option is not an empty placeholder |
button_no_text / submit_no_value |
Submit buttons with no visible text or value |
broken_describedby |
aria-describedby pointing at an id that doesn't exist |
image_no_alt |
<img> elements without an alt attribute |
iframe_no_title |
<iframe> elements without a title |
missing_autocomplete |
Common email/tel/name fields without autocomplete tokens (reported when 2 or more) |
empty_lang |
Elements with an empty lang attribute |
Hidden, submit, button, reset, and image inputs are skipped by the label check, and a single standalone checkbox (for example a consent box) does not require a fieldset.
Fix Safe Issues
Fix safe issues applies deterministic repairs to the form markup, saves it, and re-runs the audit:
- Adds a missing
idto each visible control (derived from itsname, deduplicated). - Inserts a
<label for>before any unlabelled control, using a humanized version of the field name. - Adds
aria-required="true"to fields markedrequired. - Adds
autocompleteto common fields by name:email,phone/tel,first_name,last_name,name. - Gives empty buttons an accessible name (
aria-label="Submit form"). - Adds empty
alt=""to images with no alt attribute (treating them as decorative). - Adds a
title("Embedded content") to untitled iframes.
It never renames fields and never changes submitted values -- name attributes, field types, and options are untouched, so existing submissions, actions, and integrations keep working.
Issues that require a judgment call are reported but not auto-fixed: wrapping option groups in <fieldset>/<legend>, writing descriptive button text, repairing broken aria-describedby targets, and adding a placeholder option to required selects. Fix those in the visual builder or the code editor.
Notes
- Both audit and fix require the
edit_formscapability and are protected by a per-form nonce. - After a fix, the page reloads so the builder shows the repaired markup.
- The generated labels are simple starting points (e.g.
first_namebecomes "First Name"); reword them to match your form's tone. - A
parse_errorresult means the markup couldn't be parsed at all -- fix the invalid HTML in the code editor first.