- Home
- Custom Skills
- Form Accessibility Audit
Form Accessibility Audit
Audits form HTML for label associations, error messaging, focus management, keyboard nav, autocomplete.
Rating
Votes
0
score
Downloads
0
total
Price
Free
No login needed
Works With
About
Forms are where accessibility goes to die. Not because developers don't care — because forms touch every hard thing at once: labels, focus, errors, keyboard, screen readers, autofill, validation, required marking, and the moment after submit when something goes wrong and the user needs to know what. Get any one of those wrong and the form stops being usable for someone.
This skill walks Claude through a structured accessibility audit of form HTML or JSX the user pastes. Six passes, in a fixed order: label associations, required-field marking, error messaging, focus management, keyboard navigation, and autocomplete attributes. Each pass has a checklist of the violations that actually happen in shipped code — not a theoretical list, the ones that keep showing up.
Label associations get the first pass because they break everything downstream. A placeholder is not a label. An aria-label on an input with visible text nearby is a duplicate announcement. A label that's visually adjacent but not programmatically associated is invisible to screen readers. The skill checks each input against these patterns and names the specific fix.
Error handling gets the longest pass. The skill verifies: errors are announced (not just shown), errors reference the field, focus moves to the first error after submit, the field is marked aria-invalid, the error message uses aria-describedby, and the error itself answers "what went wrong and how to fix it". Miss any one of those and a screen-reader user fills the form out, hits submit, and hears nothing while the page quietly rejects them.
Autocomplete gets a pass because it's the cheapest accessibility win nobody does. One attribute (autocomplete="email", autocomplete="name") and users with motor or cognitive disabilities — plus everyone else — save real effort. The skill lists every input and the autocomplete token that belongs on it.
Pair with Form Label Audit prompt for a lighter single-pass version, The Accessibility Auditor for a conversation about tradeoffs, and Screen Reader Walkthrough prompt to rehearse how the form actually announces.
Who this is for: frontend devs, form designers, and <span class="whitespace-nowrap">a-gnt</span> accessibility leads who have ever watched a screen-reader user abandon a signup form in silence. Not a replacement for testing with real users on real assistive tech — a way to catch the 80% of issues that are mechanical before you spend someone's time.
Don't lose this
Three weeks from now, you'll want Form Accessibility Audit again. Will you remember where to find it?
Save it to your library and the next time you need Form Accessibility Audit, it’s one tap away — from any AI app you use. Group it into a bench with the rest of the team for that kind of task and you can pull the whole stack at once.
⚡ Pro tip for geeks: add a-gnt 🤵🏻♂️ as a custom connector in Claude or a custom GPT in ChatGPT — one click and your library is right there in the chat. Or, if you’re in an editor, install the a-gnt MCP server and say “use my [bench name]” in Claude Code, Cursor, VS Code, or Windsurf.
a-gnt's Take
Our honest review
Think of this as teaching your AI a new trick. Once you add it, audits form html for label associations, error messaging, focus management, keyboard nav, autocomplete — no extra apps or complicated setup needed. It's verified by the creator and completely free. This one just landed in the catalog — worth trying while it's fresh.
Tips for getting started
Save this as a .md file in your project folder, or paste it into your CLAUDE.md file. Your AI will automatically use it whenever the skill is relevant.
Soul File
---
name: Form Accessibility Audit
description: Six-pass accessibility audit of form HTML or JSX covering labels, required marking, errors, focus, keyboard, and autocomplete.
when_to_use: User pastes a form and asks for an accessibility review, or reports a form that screen-reader users struggle with.
---
# Form Accessibility Audit
## What this skill does
Runs six fixed passes over form markup — label associations, required marking, error messaging, focus management, keyboard navigation, autocomplete — and returns specific, ranked fixes. Built for the violations that actually ship, not a theoretical checklist.
## When to load this skill
Load when the user pastes a `<form>`, a set of inputs, a JSX form component, or describes a form flow and asks any of: "is this form accessible", "audit this form", "screen-reader user can't submit", "review for a11y", or "form label check".
## The procedure
### Step 1 — Pass one: label associations
For every input, select, textarea, and custom field, verify:
- There is a visible label (a `<label>` or equivalent).
- The label is programmatically associated: `<label for="id">` matching `id="id"`, or `<label>` wrapping the input, or `aria-labelledby` pointing to a real ID.
- Placeholder text is not being used as the only label (it disappears when typing and fails contrast on most themes).
- `aria-label` is not duplicating a visible label (screen readers announce both, which is worse than just the visible one).
- Icon-only inputs have an accessible name via `aria-label` or visually-hidden text.
For each miss, write the fix as code.
### Step 2 — Pass two: required-field marking
For every required input, verify:
- The attribute `required` (or `aria-required="true"` on custom controls) is present.
- The label indicates required status visually (an asterisk or the word "required"), and the asterisk is either wrapped in text explaining what it means or is paired with `aria-hidden="true"` and the word "required" inside a visually-hidden span.
- The form key has a pattern explanation: does the visual required marker match what the validation actually enforces? Forms where the asterisk and the validation disagree are a trust failure.
### Step 3 — Pass three: error messaging
For every field that can error, verify:
- On submit with errors, focus moves to the first errored field (not the top of the form, not the submit button).
- Each errored field has `aria-invalid="true"`.
- The error text is associated via `aria-describedby` on the field, pointing to the ID of the error element.
- The error message itself answers what happened and how to fix it ("Enter a date in MM/DD/YYYY format", not "Invalid").
- An `aria-live="polite"` region or `role="alert"` announces errors that appear after interaction.
- Server-side errors follow the same pattern — don't just redirect and flash a toast.
### Step 4 — Pass four: focus management
Check: logical tab order (follows visual order), visible focus indicators on every interactive element (not removed by `outline: none` without replacement), modal forms trap focus inside and return it on close, disabled submit buttons don't trap keyboard users waiting for a state that only mouse hover can reveal, and the first field is NOT auto-focused on page load unless the page exists only for the form (auto-focus on landing pages disorients screen-reader users who were reading the heading).
### Step 5 — Pass five: keyboard navigation
Verify: every control is reachable by Tab, every control is operable by keyboard (Space / Enter for buttons, arrow keys for radio groups, arrow keys + Home/End for sliders and spinbuttons), custom components (combobox, datepicker, multi-select) follow WAI-ARIA Authoring Practices patterns, and Escape closes any opened picker or modal. Specifically flag any `div` or `span` used as an interactive control — those almost always fail keyboard nav silently.
### Step 6 — Pass six: autocomplete and return the report
Last pass: walk every input and add the correct `autocomplete` token. Common missed ones: `autocomplete="email"`, `autocomplete="name"` (or `given-name` / `family-name`), `autocomplete="tel"`, `autocomplete="street-address"`, `autocomplete="postal-code"`, `autocomplete="new-password"` on signup, `autocomplete="current-password"` on login, `autocomplete="one-time-code"` on 2FA. Also set `type` correctly (`type="email"`, `type="tel"`, `type="url"`) — it changes mobile keyboards and is an accessibility feature.
Close the audit with a ranked fix list: blockers first (missing labels, keyboard-unreachable, broken errors), then important (error messaging quality, focus after submit), then polish (autocomplete, visible required marking). Hand off to [Screen Reader Walkthrough](/agents/prompt-screen-reader-walkthrough) to rehearse the fixed form.
## A worked example
**User:** Audit this signup form.
```jsx
<form onSubmit={handleSubmit}>
<input type="text" placeholder="Email" />
<input type="password" placeholder="Password *" />
<div>Date of birth</div>
<input type="text" />
<button type="submit">Submit</button>
{error && <div className="error">{error}</div>}
</form>
```
**Claude:** Six-pass audit. Three inputs, one submit.
**Labels (3 blockers):**
- Email input: only a placeholder. Fix:
```jsx
<label htmlFor="email">Email</label>
<input id="email" type="email" autocomplete="email" required />
```
- Password input: placeholder with asterisk as the required marker, but the asterisk isn't explained. Fix:
```jsx
<label htmlFor="password">
Password <span aria-hidden="true">*</span>
<span className="visually-hidden">(required)</span>
</label>
<input id="password" type="password" autocomplete="new-password" required />
```
- Date of birth: the `<div>` is not a label at all. The input has no association. Fix:
```jsx
<label htmlFor="dob">Date of birth</label>
<input id="dob" type="text" inputMode="numeric"
placeholder="MM/DD/YYYY" autocomplete="bday"
aria-describedby="dob-help" />
<div id="dob-help">Use the format MM/DD/YYYY (example: 04/13/2026).</div>
```
**Required marking:** email is visually unmarked; placeholder "Email" doesn't say required. Add an asterisk + visually-hidden "(required)" span to the label, matching the password pattern.
**Error messaging (blocker):** `{error && <div className="error">{error}</div>}` is visible but:
- Not announced to screen readers (no `role="alert"` or `aria-live`).
- Not associated with the failing field.
- Generic message — assumed based on "error" state.
Fix: use a `role="alert"` container at the top, focus the first invalid field on submit, set `aria-invalid="true"` on it, and reference the error via `aria-describedby`:
```jsx
<div role="alert" aria-live="polite">
{formError && <p>{formError}</p>}
</div>
{/* per-field errors */}
<input id="email" ... aria-invalid={!!errors.email}
aria-describedby={errors.email ? "email-error" : undefined} />
{errors.email && <div id="email-error">{errors.email}</div>}
```
**Focus management:** no focus-after-submit logic. Add a `useEffect` (or equivalent) that focuses the first invalid field when `errors` changes. Verify the submit button still has a visible focus ring.
**Keyboard:** all native elements, so nothing broken — but make sure `outline: none` isn't in the global stylesheet without a replacement focus ring.
**Autocomplete:** `email`, `new-password`, `bday` all added above. Also change the email input from `type="text"` to `type="email"` — enables mobile email keyboard.
**Ranked fix list:**
1. **Block ship:** labels on all three inputs (breaks screen-reader use entirely), error announcement (silent failure).
2. **Fix this sprint:** focus management on submit, required marking, autocomplete tokens.
3. **Backlog:** confirm no global `outline: none` override.
Want me to run the screen reader rehearsal on the fixed version?
**User:** Yes.
**Claude:** Loading the screen reader rehearsal skill...
## What this skill will NOT do
- Will NOT declare a form "accessible" after a static audit. Real testing with assistive tech is still required.
- Will NOT fabricate what an error message should say if the validation logic wasn't shared. It asks.
- Will NOT skip passes. Every form gets all six, in order, even when one pass returns empty.
- Will NOT recommend `aria-label` as a workaround for a missing visible label unless the field is truly icon-only. Visible labels win.
- Will NOT audit the backend, network behavior, or security of the form. Accessibility only.What's New
Initial release
Ratings & Reviews
0.0
out of 5
0 ratings
No reviews yet. Be the first to share your experience.