mgifford/accessibility-skills/forms
Claude Code and agent skill by mgifford/accessibility-skills
- community
Checking that the SKILL.md file is still in the repository.
Load this skill whenever the project contains forms, inputs, selects, checkboxes, radio buttons, text areas, or any validation flow. Under no circumstances create a form without visible labels, error identification, and keyboard accessibility. Absolutely always associate every input with a label and provide clear, accessible error messages.
Install
npx vskill@latest install mgifford/accessibility-skills/formsSKILL.md
Forms Accessibility Skill
Canonical source:examples/FORMS_ACCESSIBILITY_BEST_PRACTICES.mdinmgifford/ACCESSIBILITY.mdThis skill is derived from that file. When in doubt, the example is authoritative.
Apply these rules when implementing or reviewing any form, input, or validation flow. Only load this skill if the project contains forms.
Core Mandate
Forms must be understandable and operable with keyboards, touch, speech input, screen readers, screen magnification, browser autofill, password managers, and other assistive technologies. Requirements apply to initial entry, validation, recovery, review, submission, and authentication. Users must be able to complete time-limited forms when a time limit is not essential, and complete the form at 200%/400% zoom without losing content or functionality.
Prefer native HTML controls. Build a custom widget only when native controls cannot meet the documented requirement, and implement the applicable keyboard, focus, name, role, state, and value behaviour.
Severity Scale (this skill)
| Level | Meaning | |
|---|---|---|
| Critical | Blocks task completion entirely for one or more disability groups | |
| Serious | Significantly impairs access; workaround unreasonable to expect | |
| Moderate | Creates friction; workaround exists and is not too burdensome | |
| Minor | Best-practice gap; marginal impact on access |
Do not assign severity from the violated rule alone — determine it from the actual form and task. Consider: whether the defect blocks submission or recovery; whether it affects authentication, payment, health, legal, safety, or essential public services; how many users/controls are affected; whether a reasonable workaround exists; whether it comes from a shared component; and whether data can be lost.
Critical: Labels
Every form control must have a programmatically associated label. Missing labels are Critical — screen reader users cannot identify the field.
- Never use placeholder text as the sole label — it disappears on input, fails
contrast requirements, and is not reliably announced by all screen readers
- Required fields must be identified in text, not by colour alone
- A control nested inside its own
<label>is also valid - Use
aria-label/aria-labelledbyonly when a visible HTML label is not
practical, and ensure the accessible name includes the words users can see (speech-input users identify controls by their visible label)
- Controls whose content already supplies a name (e.g.,
<button>Save</button>)
don't need a separate label
On `aria-required`: Do not add aria-required="true" to native inputs that already have the HTML required attribute — it is redundant and adds noise to the accessibility tree. Use aria-required only on custom widgets (e.g., role="combobox", role="listbox") that cannot use the native attribute.
Required/optional fields: explain how required fields are identified before the first field (e.g., "Fields marked 'required' must be completed"). Don't rely on an asterisk or colour alone. Don't mark every optional field when marking the smaller set of required fields would be clearer, or vice versa.
Critical: Error Identification
Errors must be programmatically associated with their field. Absent error identification is Critical — blind users receive no indication something is wrong.
- Mark invalid fields with
aria-invalid="true"after validation determines
they are invalid; remove the invalid state and error association after correction
- Error messages must be specific and actionable — not just "invalid input"
- Never use colour or an icon alone to indicate an error
- Associate the error message with the field via
aria-describedby(or a
tested aria-errormessage implementation); preserve any existing hint association
- Keep the entered value unless security requires otherwise
Do not put role="alert" on error text that is already present when the page loads — a live region only announces changes made after it is established. Avoid combining several competing announcement mechanisms without AT testing.
Critical: Error Summary
Provide an error summary when several fields can fail, the form is long, errors may be outside the viewport, or users would otherwise have difficulty locating them. No error summary on multi-error, long, or complex forms is Critical.
- Place the summary before or at the beginning of the form; insert it after a
failed submission and move focus to it
- Use links that identify both the field and the problem; activating a link
must move focus to the relevant control
- Keep the inline field message as well as the summary; update the heading
count when errors change
- Avoid adding
role="alert"when focus movement already causes a clear
announcement, unless testing shows an additional live announcement helps
- Focus movement is a deliberate response to the submit action — don't move
focus on every inline validation change
Critical: Do Not Block Paste
Never block paste, copy, or standard keyboard actions on any input. Blocking paste is Critical — users with motor disabilities and those who use password managers cannot re-type credentials they cannot physically type.
Serious: Accessible Authentication (WCAG 3.3.8)
Authentication must not require users to remember, manipulate, or transcribe information unless a conforming alternative or assistance mechanism exists. At minimum:
- Allow password managers to identify and fill username/password fields
- Allow copy and paste into username, password, and verification-code fields
— do not split a one-time code into controls that prevent pasting the whole code
- Do not ask for selected characters from a password
- Use appropriate autocomplete tokens (
username,current-password,new-password,
one-time-code)
- Provide a multi-factor path that doesn't require unsupported transcription
or a cognitive puzzle; account recovery must meet the same requirements as login
- If a CAPTCHA or cognitive test is used, evaluate it against WCAG 3.3.8 and
provide an applicable alternative
A show-password button must update its visible label/pressed state consistently, preserve focus, and not clear the value.
Serious: Grouping Related Controls
Use <fieldset> + <legend> for related controls. Missing grouping is Serious — radio and checkbox groups become unintelligible without a group label.
Keep legends concise; don't use <fieldset> solely for visual styling. For a checkbox set that allows multiple selections, state that users may select more than one.
Serious: Input Types
Choose type, autocomplete, and inputmode independently according to what the value means. This surfaces the correct virtual keyboard on mobile and provides semantic meaning to AT.
| Information | Recommended control | |
|---|---|---|
| Email address | type="email" autocomplete="email" | |
| Telephone number | type="tel" autocomplete="tel" | |
| Website address | type="url" autocomplete="url" | |
| Search query | type="search" | |
| Current / new password | type="password" autocomplete="current-password" / "new-password" | |
| One-time code | One text input, autocomplete="one-time-code" inputmode="numeric" | |
| Numeric quantity with increment/decrement semantics | type="number" | |
| Numeric-looking identifier, postal code, card number | type="text" with matching inputmode/autocomplete |
Do not treat all digits as numbers
Use type="number" only for values on which mathematical operations make sense and min/max/step are useful — never for identifiers or values that may contain leading zeros:
inputmode requests a virtual keyboard; it does not validate the value. Add pattern only when the resulting constraint and error message are correct for every accepted value — do not assume all users enter ASCII digits.
Date inputs
Use a native <input type="date"> when it meets the product's locale, browser, and AT requirements — test the actual implementation. For dates like date of birth, separate labelled text inputs are often easier to understand and validate than a native date picker or custom calendar widget:
Do not build a custom calendar dialog unless users need calendar-based selection; if one is required, implement and test the complete dialog and grid keyboard interaction (see the APG Date Picker pattern).
<select> — single
Native <select> is well-supported by all AT. Always include a blank/placeholder option as the first <option> when no default is appropriate.
Multiple selection
<select multiple> has poor discoverability (Shift/Ctrl-click) and is keyboard-unfriendly. Prefer checkboxes inside a `<fieldset>` for a short, known list. <select multiple> may be appropriate for expert interfaces but must be usability-tested with the intended audience; if used, add visible instructions (Hold Ctrl (or Cmd on Mac) to select multiple options.) referenced via aria-describedby.
<datalist>
Provides autocomplete suggestions for a text input; natively keyboard accessible but announcement quality varies — test with your AT matrix. Not a replacement for a fully accessible combobox when the suggestion list is the only valid set of values — use role="combobox" with the APG Combobox pattern instead.
Serious: Autocomplete for Personal Data
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/forms/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/mgifford/accessibility-skills/forms)