Accessibility for Laravel Forms: WCAG 2.2 in Practice | FilaForms                                 [ ![Filaforms Logo](https://filaforms.app/logo.svg)FilaForms

 ](https://filaforms.app)  [ Features ](https://filaforms.app#features) [ Pricing ](https://filaforms.app#pricing) [ Blog ](https://filaforms.app/blog) [ Documentation ](https://docs.filaforms.app)  [ Try Demo ](https://filaforms.app/login) [ Get Started ](https://filaforms.app#pricing)

 [ Features ](https://filaforms.app#features) [ Pricing ](https://filaforms.app#pricing) [ Blog ](https://filaforms.app/blog) [ Documentation ](https://docs.filaforms.app) [ Try Demo ](https://filaforms.app/login) [ Get Started ](https://filaforms.app#pricing)

   ![FilaForms](https://filaforms.app/logo.svg) FilaForms

 TutorialsAccessibility for Laravel Forms: WCAG 2.2 in Practice
=====================================================

 filaforms.app/blog

  [    Back to blog ](https://filaforms.app/blog) [ Tutorials ](https://filaforms.app/blog/category/tutorials)

Accessibility for Laravel Forms: WCAG 2.2 in Practice
=====================================================

 Manuk Minasyan ·  June 16, 2026  · 8 min read

 Procurement sent over a questionnaire on Wednesday. Question 14: "Is the form WCAG 2.2 AA compliant?"

The form plugin's marketing page says it "follows accessibility best practices." That isn't an answer. It's a brand promise dressed up as a fact.

Before I go further: compliance is a moving target; this gets you most of the way. A manual audit by an accessibility specialist is what gets you AA certification. What I can give you is the developer's habits checklist for an accessible Laravel form — five places where it passes or fails WCAG 2.2 in practice, what Filament's defaults handle for you, and the one place my own stack falls short.

It pairs with [the GDPR checklist for forms](/blog/gdpr-compliant-forms-laravel-checklist) — the two regulatory questions land in the same week, and the habits overlap.

What does WCAG 2.2 require from a Laravel form?
-----------------------------------------------

A Laravel form satisfies [WCAG 2.2 AA](https://www.w3.org/TR/WCAG22/) when every input has a programmatic label tied to it, the form is operable by keyboard alone with a visible focus state, errors are identified in text and announced to assistive tech, color contrast meets 4.5:1 for body text, and interactive targets are at least 24 by 24 CSS pixels. Five habits, not a feature flag.

The three WCAG categories that matter for forms
-----------------------------------------------

The WCAG 2.2 spec is long. For forms, three of its four principles do most of the work.

**Perceivable.** Users can perceive every input — its label, its current value, its state. Translates to: real labels, sufficient color contrast, no information conveyed by color alone.

**Operable.** Users can operate every control — without a mouse, without a touch screen, without precise pointing. Logical tab order, visible focus, target size, no keyboard traps.

**Understandable.** Users can understand what the form wants and what went wrong. Clear instructions, specific error messages, predictable behaviour on input.

Robust — the fourth principle — is the markup-validity rubric. Filament renders valid HTML; the rest of this post lives inside the first three.

Checklist item 1: Label association
-----------------------------------

### Every input has a real label tied to its id

Every form field needs a `` paired with an input whose `id="some-id"`. Not a placeholder. Not visually adjacent text. A programmatic association the browser and the screen reader can follow.

Placeholder-as-label is the most common fail. It looks clean, ships fast, breaks assistive tech: the placeholder disappears the moment the user types, low-contrast placeholder text fails SC 1.4.3, and screen readers don't always announce placeholders as labels.

Filament's field wrapper renders a real `` paired with the input's id by default — I verified this against the installed `field-wrapper.blade.php` in vendor. Stock form components satisfy SC 1.3.1 and 3.3.2. Where it breaks is custom field types: build a new component, forget the `` pair, you've shipped a regression.

Checklist item 2: Keyboard navigation
-------------------------------------

### Tab order is logical, focus is visible, no field is a trap

A keyboard-only user — someone on a switch device, someone with a motor disability, someone whose mouse died — has to reach every input and submit. Three habits cover this.

Tab order follows visual order. If your CSS reorders fields with `flex` or `grid` reverse, the DOM order needs to match so `Tab` walks predictably.

Focus is visible. The default browser focus ring is ugly, so people remove it. Don't remove it without replacing it. Filament's default focus styles meet SC 2.4.7; a custom theme that strips them does not.

No keyboard traps. Filament's conditional fields — the ones using `live()` plus `visible()` — can move focus when a previously-focused field hides itself. Tab through every state once. If focus lands nowhere, fix it.

Checklist item 3: Error identification
--------------------------------------

### Errors named in text, tied to the input, announced

This is where most Laravel forms — including ones built on Filament — quietly fall short.

SC 3.3.1 says errors must be identified and described in text. SC 3.3.3 says where the system can suggest a correction, it should. A generic "this field is required" passes the first bar and fails the second. "Enter your work email — we'll use it to reply" passes both.

The harder requirement is programmatic association. A screen reader reads the input's label, then text linked via `aria-describedby`, then announces `aria-invalid="true"` if set. The error has to be reachable that way — otherwise the user hears "email, edit text" and gets no idea anything went wrong.

Filament's field wrapper renders the error message with a `data-validation-error` attribute, but the input itself doesn't get `aria-describedby` or `aria-invalid` pointing back at the error. Stock behaviour today renders the error visually without binding it. That's a gap, and we'll come back to it in section 8.

Checklist item 4: Color contrast
--------------------------------

### 4.5:1 for body text, 3:1 for large text and UI components

WCAG 2.2 AA requires 4.5:1 contrast for normal text (SC 1.4.3) and 3:1 for large text and graphical UI components (SC 1.4.11). Most Filament defaults pass — both light and dark themes ship accessible palettes.

Custom themes are where contrast fails happen. The `--primary-500` you picked to match the brand may render labels at 3.8:1 on white. Helper text is the second offender — gray sub-labels in the 3.0–4.0 range are the most common fail I see.

Run every text-on-background pair through [the WebAIM contrast checker](https://webaim.org/resources/contrastchecker/) before you ship a custom theme. The list of pairs is shorter than you think — label, helper text, placeholder, error, submit button, link. Six checks, done.

Checklist item 5: Target size
-----------------------------

### Interactive controls are at least 24 by 24 CSS pixels

This is the WCAG 2.2 addition that catches forms by surprise. SC 2.5.8 Target Size (Minimum) requires interactive targets to be at least 24 by 24 CSS pixels — measured at the click target, not the visible icon.

Filament's default inputs and buttons clear this bar. Where forms fail is custom additions: a small inline "remove" icon on a repeater row, a 16-pixel info tooltip, a tight social-icon row above the submit. If you built it with a `w-4 h-4` button, you're under the bar.

The spec exception is "essential" presentation — but exceptions are an auditor's red flag. Pad the click target instead. The visible icon stays 16 pixels; wrap it in a button with enough padding and you've satisfied both the spec and the design.

What FilaForms gives you for free — and what we don't
-----------------------------------------------------

FilaForms is accessibility-friendly by default. Compliance is a set of habits, not a feature.

What you get: real `` association on every stock field, keyboard navigation through every input, visible focus rings, valid HTML, and Filament's default palette — which clears AA contrast for stock themes.

What you don't get yet: a stock Filament input doesn't carry `aria-describedby` pointing at its error message, and doesn't toggle `aria-invalid="true"` when validation fails. That's a gap. We use a small wrapper override on public forms, but it isn't shipped as a config flag yet. There's also no automated contrast check on theme save, and no accessibility audit dashboard. Both are on the roadmap. I'd rather name the gap than ship a "WCAG 2.2 AA compliant" badge an audit would tear down.

FAQ
---

### Is FilaForms WCAG 2.2 AA compliant?

A package can't be certified compliant on its own — compliance is a property of the form as shipped, including theme, copy, and custom fields. FilaForms is accessibility-friendly by default and gets you through most of the WCAG 2.2 AA criteria for forms. Final certification needs a manual audit.

### Does Filament emit `aria-describedby` on inputs with errors?

Not by default in the stock field wrapper. Errors render with a `data-validation-error` attribute and stay visually adjacent, but the input doesn't get a programmatic pointer to them. A small Blade override fixes it; we ship a habit, not a config flag, today.

### What's the difference between WCAG 2.1 and WCAG 2.2 for forms?

WCAG 2.2 added nine new success criteria. The two that hit forms hardest are 2.5.8 Target Size (Minimum) at 24×24 CSS pixels, and 3.3.7 Redundant Entry — don't make users re-type information already provided in the same flow.

### Does a procurement questionnaire need an audit, or is self-attestation enough?

Depends on the buyer. Most enterprise procurement accepts a documented self-assessment plus a remediation plan. Public-sector procurement in the EU and US increasingly requires a third-party audit or a VPAT. Check the questionnaire's evidence column.

The takeaway
------------

An a11y Laravel form isn't a checkbox. It's five habits — label, keyboard, error identification, contrast, target size — applied to every public form, every custom theme, and every new field type. Get them right and the procurement questionnaire stops being a blocker.

FilaForms makes most of them easier. The error-association gap on an accessible form built with Filament is one we own and document. The rest is your call on theme, copy, and custom controls.

Coming up: [the job-application form walkthrough](/blog/job-application-forms-in-laravel) — the public-facing form where every WCAG 2.2 form criterion above matters most.

 Related posts
-------------

 [  Tutorials   Jun 2, 2026

 GDPR-Compliant Forms in Laravel: A Practical Checklist
--------------------------------------------------------

GDPR compliance isn't a feature you buy — it's a set of habits. Here's the checklist we follow when building forms that collect data from EU users.

 ](https://filaforms.app/blog/gdpr-compliant-forms-laravel-checklist) [  Tutorials   May 22, 2026

 Stop Spam in Laravel Forms: Honeypot, Rate Limits, and Smarter Defaults
-------------------------------------------------------------------------

reCAPTCHA isn't the answer. Or at least, it's not the first answer. Here's the layered approach we use to keep junk out of FilaForms submissions.

 ](https://filaforms.app/blog/stop-spam-laravel-forms-honeypot-rate-limits) [  Tutorials   Apr 30, 2026

 File Uploads in Filament Forms: Storage, Validation, and Security
-------------------------------------------------------------------

File uploads are where most form builders cut corners. They'll let you add a file field and call it done, leaving you to figure out storage and validation

 ](https://filaforms.app/blog/file-uploads-in-filament-forms-storage-validation-and-security)

    ![FilaForms Logo](/logo.svg) FilaForms

 Laravel form infrastructure for Filament. Stop rebuilding forms on every project.

 ### Product

 [ Features ](https://filaforms.app#features) [ Documentation ](https://docs.filaforms.app) [ Blog ](https://filaforms.app/blog) [ Pricing ](https://filaforms.app#pricing) [ Contact ](mailto:hello@filaforms.app)

 ### Legal

 [ Terms of Service ](https://filaforms.app/terms-of-service) [ Privacy Policy ](https://filaforms.app/privacy-policy)

  © 2025-2026 FilaForms. All rights reserved.

 [    ](mailto:hello@filaforms.app) [    ](https://x.com/MinasyanManuk)
