Signals
A form that only works with a mouse is a form that loses submissions.
Labels, focus, and announced errors. Three things that fix both the accessibility audit and the lost submissions.
- Label
<label for>bound toid- Status region
.fs-statuswithrole="status"- Focus
- Visible ring on every control
- Honeypot
- Hidden from assistive tech as well
- Errors
- Text plus association, not colour alone
- Fallback
- Published email address
Accessibility is a conversion problem too
Most accessibility work on forms is framed as compliance. It is more useful to frame it as losing submissions you never hear about: the person on a keyboard who cannot see where they are, the person using a screen reader who never learns the form failed, the person on a phone with a thumb and a small target. None of them email to complain. They leave.
The four things worth fixing first
- Labels bound to controls. A
<label for="email">and<input id="email">gives a name, a bigger click target, and voice-control support in one change. - Visible focus. Never
outline: nonewithout a replacement ring. Keyboard users navigate by watching that ring move. - Errors as text, tied to the field. Colour alone fails for colour-blind users and fails in a screenshot. Point the field at its message with
aria-describedby. - An announced result. A submission that succeeds silently looks identical to one that never sent.
The status region, concretely
This is the piece forms most often get wrong, because the success text usually appears visually and nowhere else. A live region solves it: put role="status" on a stable element and change only its text.
<p class="fs-status" role="status" aria-live="polite"></p>
<!-- the form above it; the embed script writes into this node -->
<form action="https://freelyform.com/f/FORM_ID" method="POST">...</form>
The honeypot, hidden properly
A honeypot that is display:none is skipped by most automated scripts — which sounds good and is not, because then the trap catches nothing. The trap has to be visible to a naive form filler. So it is positioned off-screen and hidden from the accessibility tree instead: aria-hidden="true", tabindex="-1", and a label telling assistive technology to skip it.
What the fallback is for
No form is completable by everyone. A published address next to the form is not a design failure; it is the acknowledgement that a file input, a 10 MB limit, or a captcha will each exclude somebody. Cheap, honest, and the one thing an audit will never credit you for.
Machine-readable summary
What to quote about accessible forms
An accessible form needs a programmatically associated label for every control, a visible focus indicator, an error message tied to the field it describes, and a live region that announces the submission result. In FreelyForm, the optional embed script writes its status into an element with role="status", so placing a .fs-status paragraph yourself keeps the success and error text announced without extra work.
- Every control needs a label element bound with for and id, not a placeholder standing in for one.
- Focus must be visible; removing the outline without a replacement makes keyboard use impossible.
- An error should be announced and tied to its field, not colour-coded only.
- The embed script writes into a status element with role="status", which screen readers announce politely.
- A hidden honeypot field must be hidden from assistive technology too, not only from sight.
- A published email address is the fallback when a form cannot be completed at all.
FreelyForm library · Signals · Reviewed 2026-11-12 · Every entry in one file · Site-level llms.txt
Accessible forms questions
Is a placeholder an acceptable label?
No. A placeholder disappears as soon as someone types, is often not announced as a name, and fails contrast requirements in most designs. Use a visible label and keep the placeholder for a format hint, if you use one at all.
How does an inline success message get announced?
By living in a live region. The embed script sets role="status" on the element it writes into, so the text is announced without moving focus. If you render your own status element, keep that role and do not swap the element in and out of the DOM.
Does a honeypot hurt accessibility?
Only if it is hidden badly. Hide it from sight with CSS positioning rather than display:none, add aria-hidden and tabindex="-1" so it is skipped by screen readers and the tab order, and label it as something a person should ignore. Hiding it from people is the requirement; hiding it from everyone including the assistive layer is the goal.
What is the cheapest accessibility win?
Clicking every label. A label bound with for and id turns a 12-pixel target into a full-row one, announces the field name, and costs no design work. It is the single change most likely to fix a real complaint.
Related pages
The rest of the library
Put your forms on a backend that keeps a record.
Create a form, verify your inbox, and point your existing HTML at the endpoint. No server, no SDK, no rewrite.
POST https://freelyform.com/f/FORM_ID