TL;DR: Forms are where government accessibility succeeds or fails, because forms are where people actually get something done — applying for a permit, paying a bill, registering for service. Every input needs a programmatically associated
<label>, related fields belong in a<fieldset>with a<legend>, and errors must be identified in text (SC 3.3.1) with suggestions for fixing them (SC 3.3.3). Useautocompleteattributes (SC 1.3.5) so users can fill fields with stored data. WCAG 2.2 adds two form-relevant criteria: SC 3.3.7 Redundant Entry (don’t make people re-enter what they already gave you) and SC 3.3.8 Accessible Authentication (don’t force a cognitive test like a CAPTCHA or memorized password to log in). Tools like axe and Govzu catch missing labels automatically; error handling and focus order need human testing.
If your government website has a form, that form is almost certainly the highest-stakes accessibility surface you own. An inaccessible image is a problem. An inaccessible government form is a person who cannot apply for a disability parking placard, cannot pay a water bill, cannot register to vote, or cannot submit a public-records request. Forms are where accessibility failures turn into denied access to government services — which is exactly what ADA Title II prohibits.
The DOJ’s 2024 final rule requires state and local government websites to conform to WCAG 2.2 Level AA, with compliance deadlines in April 2026 for larger entities (population 50,000+) and April 2027 for smaller ones. Forms touch a large share of the WCAG 2.2 success criteria, and WCAG 2.2 added two new criteria — SC 3.3.7 and SC 3.3.8 — that apply almost exclusively to forms and authentication. This guide walks through what an accessible form actually requires, with code you can adapt for permit applications, payment forms, and contact forms.
Start With Labels: SC 1.3.1, 3.3.2, 4.1.2
Every form control — text input, checkbox, radio button, select, textarea — needs a label that is programmatically associated with the control, not just visually near it. A screen reader user who tabs to an input hears the label; without one, they hear “edit, blank” and have no idea what to type.
The simplest, most robust approach is a real <label> element with a for attribute matching the input’s id:
<label for="applicant-name">Full legal name</label>
<input type="text" id="applicant-name" name="applicant-name" autocomplete="name">
Wrapping the input inside the label also works and removes the need to match for/id:
<label>
Full legal name
<input type="text" name="applicant-name" autocomplete="name">
</label>
A few rules that trip up government teams:
- Placeholder text is not a label.
placeholder="Full legal name"disappears the moment a user types, fails contrast checks, and is not reliably announced by assistive technology. Use a visible<label>and reserve the placeholder for an example format if you need one at all. - Don’t hide the label visually unless you must. Sighted users with cognitive disabilities benefit from persistent labels too. If a design truly requires a label-less search box, use
aria-label(covered in our ARIA labels guide). - Required indicators belong in the accessible name. A red asterisk alone is not enough; pair it with the
requiredattribute and, ideally, the word “required.”
Group Related Fields With Fieldset and Legend
Radio buttons and checkboxes that belong to a single question must be grouped so a screen reader announces the question, not just the individual options. The native mechanism is <fieldset> with a <legend>:
<fieldset>
<legend>What type of permit are you applying for?</legend>
<input type="radio" id="permit-building" name="permit-type" value="building">
<label for="permit-building">Building permit</label>
<input type="radio" id="permit-electrical" name="permit-type" value="electrical">
<label for="permit-electrical">Electrical permit</label>
<input type="radio" id="permit-plumbing" name="permit-type" value="plumbing">
<label for="permit-plumbing">Plumbing permit</label>
</fieldset>
Now a screen reader announces “What type of permit are you applying for? Building permit, radio button, 1 of 3.” Without the <fieldset>/<legend>, the user hears only “Building permit, radio button” with no idea what the choice is about. Use the same pattern for address blocks, multi-part name fields, and any group of inputs that share a single prompt.
Turn On Autocomplete: SC 1.3.5
SC 1.3.5 Identify Input Purpose (Level AA) requires that inputs collecting information about the user expose their purpose programmatically, using the HTML autocomplete attribute with its standard token values. This lets browsers and assistive technologies auto-fill fields and lets some users overlay symbols or simplified language on common fields. It’s also just a better experience — people fill out government forms faster when the browser offers their saved address.
<label for="email">Email address</label>
<input type="email" id="email" name="email" autocomplete="email">
<label for="street">Street address</label>
<input type="text" id="street" name="street" autocomplete="street-address">
<label for="zip">ZIP code</label>
<input type="text" id="zip" name="zip" autocomplete="postal-code"
inputmode="numeric">
Use the official token list (name, email, tel, street-address, postal-code, bday, cc-number, and so on). SC 1.3.5 applies specifically to fields about the user — so a permit applicant’s own address gets autocomplete, but a free-text “describe the work to be done” field does not.
Error Identification and Suggestions: SC 3.3.1 and 3.3.3
This is where most government forms break down. The two criteria work together:
- SC 3.3.1 Error Identification (Level A): if an input error is detected, the item in error must be identified in text. Color or a red border alone is not enough.
- SC 3.3.3 Error Suggestion (Level AA): if you know how to fix the error, tell the user how, in text. “Invalid” is not a suggestion; “Enter a date in MM/DD/YYYY format” is.
Tie the error message to the input with aria-describedby, mark the field as invalid with aria-invalid="true", and use text — not just color — to flag the problem:
<label for="ssn">Social Security number</label>
<input
type="text"
id="ssn"
name="ssn"
inputmode="numeric"
aria-describedby="ssn-error"
aria-invalid="true"
autocomplete="off">
<p id="ssn-error" class="field-error">
Enter a 9-digit Social Security number with no dashes, for example 123456789.
</p>
When the screen reader user focuses the field, they hear the label, the value, and the error message and suggestion. Sighted users see the text message, not just a red outline.
Announce the error summary
For forms that validate on submit, move focus to an error summary at the top of the form and give it a heading. A summary like “There are 3 problems with your application” with in-page links to each field is one of the most effective accessibility patterns there is — and it helps everyone, not only assistive-technology users.
<div role="alert" tabindex="-1" id="error-summary">
<h2>There are 2 problems with your application</h2>
<ul>
<li><a href="#ssn">Social Security number must be 9 digits</a></li>
<li><a href="#email">Enter a valid email address</a></li>
</ul>
</div>
Set focus to this container with JavaScript after a failed submit so screen reader users are taken straight to the problems.
Don’t Validate Hostilely
A handful of patterns technically pass but make forms miserable:
- Don’t clear the form on error. Re-entering an entire permit application because one ZIP code was wrong is a barrier (and runs straight into SC 3.3.7, below).
- Don’t block paste in fields like card numbers or confirmation codes. People who rely on password managers or who copy from another document need to paste.
- Don’t auto-advance focus between fields (the “split code” pattern) without testing it with a keyboard and screen reader — it frequently traps or disorients users.
- Give time to fix errors. If a session times out, warn the user and let them extend it (SC 2.2.1).
Focus Order and Keyboard Operability: SC 2.4.3, 2.1.1
A keyboard user must be able to reach and operate every control in a logical order using Tab, Shift+Tab, Space, and Enter — see our keyboard accessibility guide for the full picture. For forms specifically:
- Match DOM order to visual order. Avoid positive
tabindexvalues; they override the natural order and create confusing jumps. Usetabindex="0"only to make custom controls focusable andtabindex="-1"only for programmatic focus targets like the error summary. - Use native controls. A native
<select>,<input type="date">, or<button>is keyboard-operable for free. A<div>styled to look like a dropdown is not — and rebuilding that behavior with ARIA is far more work than it’s worth. - Make the visible focus indicator obvious (SC 2.4.7, and the stronger SC 2.4.11 Focus Not Obscured added in 2.2). Don’t remove the focus outline in CSS without replacing it with something at least as visible.
New in WCAG 2.2: SC 3.3.7 Redundant Entry
SC 3.3.7 Redundant Entry (Level A) says that information a user already entered in the same process must be either auto-populated or available to select again — you can’t make them retype it. This is a Level A criterion, so it’s a baseline requirement, and government multi-step forms violate it constantly.
The classic example is the “billing address same as mailing address” checkbox. If a permit applicant entered their address on step 1, step 3 should not demand they type it again from memory:
<fieldset>
<legend>Billing address</legend>
<label>
<input type="checkbox" id="same-as-mailing" name="same-as-mailing">
Same as mailing address
</label>
</fieldset>
When checked, copy the earlier values into the billing fields. Exceptions exist for re-entering a password to confirm it, or where re-entry is essential (a security check), but in general: if your form already has the data, fill it in.
New in WCAG 2.2: SC 3.3.8 Accessible Authentication
SC 3.3.8 Accessible Authentication (Minimum) (Level AA) prohibits requiring a cognitive function test — remembering a password, solving a puzzle, transcribing characters — as the only way to log in or authenticate, unless an alternative is provided. This matters for any government portal with accounts: tax payment systems, utility billing, business licensing, university student portals.
What this means in practice:
- Allow password managers and paste. Don’t block paste into password fields, and don’t break autofill. Supporting
autocomplete="current-password"and copy/paste is often enough to satisfy the criterion. - Avoid traditional image CAPTCHA. Transcribing distorted text or solving an image puzzle is a cognitive function test. Prefer non-cognitive methods — a checkbox confirmation, a token-based or device-based check, or an honeypot field. If you must use a challenge, provide an accessible alternative path.
- Support modern, low-friction auth. Email “magic links,” passkeys/WebAuthn, and OAuth (“sign in with your existing account”) generally don’t impose a cognitive test and satisfy 3.3.8 well.
<label for="password">Password</label>
<input
type="password"
id="password"
name="password"
autocomplete="current-password">
<!-- Allow showing the password and pasting; do not disable either. -->
<button type="button" aria-pressed="false" id="toggle-password">
Show password
</button>
CAPTCHA in particular is a recurring problem on government login and contact forms. SC 3.3.8 doesn’t ban it outright, but it does mean an image-only CAPTCHA with no accessible alternative is now a clear WCAG 2.2 AA failure.
A Quick Build Checklist
Before you ship a government form, confirm each item:
| Item | Criterion | Check |
|---|---|---|
Every control has an associated <label> | 1.3.1, 4.1.2 | axe / manual |
Related controls grouped in <fieldset>/<legend> | 1.3.1 | manual |
Required fields use required and say “required” | 3.3.2 | manual |
autocomplete on personal-data fields | 1.3.5 | manual |
Errors identified in text, tied via aria-describedby | 3.3.1 | screen reader |
| Error messages suggest how to fix | 3.3.3 | manual |
| Error summary receives focus on submit | 3.3.1, 2.4.3 | screen reader |
Logical focus order, no positive tabindex | 2.4.3 | keyboard |
| Visible focus indicator, not obscured | 2.4.7, 2.4.11 | keyboard |
| Already-entered data isn’t re-requested | 3.3.7 | manual |
| Login doesn’t require a cognitive test | 3.3.8 | manual |
CMS-Specific Notes
WordPress: Popular form plugins (Gravity Forms, WPForms, Formidable) generate labels and fieldset markup, but their default error handling and CAPTCHA add-ons frequently fail 3.3.1, 3.3.3, and 3.3.8. Audit the rendered HTML, not the builder UI, and replace image CAPTCHA with an accessible anti-spam method.
Drupal: Drupal’s Form API produces strong, label-associated markup by default and is one of the better starting points for accessible forms. Watch out for contributed modules and AJAX-driven multi-step flows that move focus unpredictably.
Granicus / CivicPlus / Tyler: Hosted gov platforms vary widely. Their form builders often emit placeholder-as-label patterns and color-only error states. Because you usually can’t edit the templates, document the failures and push them to the vendor — and include accessible-forms requirements in your next procurement and VPAT review.
Forms also belong on the broader WCAG 2.2 AA checklist and are among the top accessibility failures auditors find on government sites — partly because automated tools catch missing labels but miss broken error handling and focus management, which require manual testing. Plan a full accessibility audit that includes keyboard and screen reader walkthroughs of every form.
Forms are the part of your website where accessibility and basic public service overlap most directly — and because they’re built once but used daily, a single broken pattern compounds across thousands of interactions. Automated tools verify labels and structure; human testing verifies that errors, focus, and authentication actually work for someone using a screen reader or keyboard. Govzu continuously monitors your government site for form accessibility regressions — flagging a missing label or a new color-only error state the moment a contractor ships it, so a fixed form stays fixed long after the audit is filed.