The contact form audit: labels, autocomplete, input types, and the 16 pixel rule
Most contact forms fail for reasons you can check in ten minutes. Here is the accessible contact form audit: real labels, autocomplete tokens, input types, and font size.

The contact form is usually the most valuable element on a small business website and the least audited. It gets designed once, styled to match the brand, tested by the person who built it on a desktop browser with a mouse, and then never looked at again. Meanwhile every lead the site will ever produce has to pass through it.
Four things break contact forms more than anything else, and all four are visible in the markup. None of them require a usability study. You can check every one of them on a page in about ten minutes with browser devtools and a phone.
Real labels, not visible captions
A form looks finished when every field has text sitting next to it. That text is only a label if the code says so. An accessible contact form connects each caption to its input in one of two ways:
<!-- explicit: for matches id -->
<label for="email">Email address</label>
<input id="email" type="email" name="email">
<!-- implicit: label wraps the input -->
<label>
Email address
<input type="email" name="email">
</label>
If neither connection exists, a screen reader announces the field as "edit, blank" and the person filling it in has to guess from context. The connection also widens the click target: tapping a properly associated label focuses its input, which matters more on a phone than on a desktop.
The fastest way to test this is to click the caption text. If the cursor jumps into the field, the label is wired up. If nothing happens, it is decoration. Run that click test on every field in the form, including checkboxes and radio buttons, which fail this test more often than text inputs do.
Radio and checkbox groups need one more layer. The individual options get their own labels, and the question that groups them belongs in a <fieldset> with a <legend>. Without it, someone hears "Email, radio button, 1 of 3" with no idea that the question was "How should we contact you?"
Placeholders are not labels
Placeholder text is the single most common substitute for a real label, and it fails in four separate ways.
It disappears the moment someone starts typing, so anyone who gets interrupted loses the only description of the field. It is not reliably announced as the accessible name by assistive technology. Its default styling is low contrast grey on white, which routinely fails the 4.5:1 contrast ratio that WCAG requires for text. And it defeats review: a filled form with placeholder-only labels gives the person no way to confirm that the number they typed went in the phone field rather than the postal code field.
Placeholders are fine as format hints next to a real label. "Email address" as the label, "you@company.com" as the placeholder. They are never a replacement.
Autocomplete tokens, the attribute most forms skip
Browsers and password managers can fill a contact form instantly, but only when each field declares what it holds. That declaration is the autocomplete attribute, and it takes a specific token, not a guess:
<input id="name" type="text" name="name" autocomplete="name">
<input id="email" type="email" name="email" autocomplete="email">
<input id="phone" type="tel" name="phone" autocomplete="tel">
<input id="company" type="text" name="company" autocomplete="organization">
<input id="zip" type="text" name="zip" autocomplete="postal-code"
inputmode="numeric">
The full token list lives in the MDN autocomplete reference. Use the exact strings. A made-up value like autocomplete="user-email" is ignored, and so is autocomplete="on" with nothing to specify.
This is not only a convenience feature. WCAG 2.2 success criterion 1.3.5, Identify Input Purpose, exists because people with motor impairments, memory impairments, and cognitive disabilities depend on autofill to complete a form at all. Someone who types slowly or painfully gets a seven-field form down to one tap. Skipping the attribute takes that away.
Two notes on correctness. Split name fields need given-name and family-name rather than name on both. And the message textarea has no meaningful token, so leave autocomplete off it entirely rather than inventing one.
Input types that match the data
The type attribute does three jobs at once: it tells the browser which on-screen keyboard to show, which built-in validation to apply, and which autofill entries are relevant. Defaulting everything to type="text" throws away all three.
On a phone, type="email" produces a keyboard with the @ symbol and the period on the primary layer. type="tel" produces the numeric keypad. type="url" adds the slash. Someone entering an email address on a text field has to switch keyboard layers twice for every submission.
Two patterns are worth knowing because they go wrong consistently:
- Do not use
type="number"for phone numbers, postal codes, or anything else that is a digit string rather than a quantity. It strips leading zeros, adds spinner arrows, and rejects the parentheses and dashes people actually type. Usetype="text"withinputmode="numeric"instead. inputmodecontrols the keyboard independently oftype, so you can keep real text validation and still get the right keypad. The MDN input element reference lists every type and the validation each one applies.
Keep client-side validation permissive. A pattern attribute that rejects a valid international phone number costs a real lead, and server-side validation is the one that actually protects you.
The 16 pixel rule
Open your contact form in Safari on an iPhone and tap the first field. If the page zooms in, the computed font size on that input is below 16px.
That is deliberate behavior, not a bug. Mobile Safari zooms the viewport when a focused input would otherwise render text too small to read. The zoom then leaves the layout shifted sideways, so the person has to pinch back out between every field. On a six-field form that is five extra gestures and a visible stutter on the highest-intent interaction on the site.
The fix is one line:
input, select, textarea { font-size: 16px; }
Inputs do not inherit font-size from their parent by default, which is why forms styled with a 14px body size so often end up at the browser default inside the fields. Set it explicitly on the controls themselves.
There is a second, worse fix that still shows up in production code: adding maximum-scale=1 or user-scalable=no to the viewport meta tag. It stops the zoom by disabling pinch zoom for the whole page, which breaks magnification for every low vision user on the site and fails WCAG success criterion 1.4.4. If you find that in a theme or a template, remove it and fix the font size instead.
While you are on the phone, check target size. WCAG 2.2 sets a 24 by 24 CSS pixel minimum for interactive targets, and a checkbox styled down to 16 pixels with the label floating beside it misses it. Associating the label, as above, usually fixes this for free.
Errors that only exist in red
Last pass. Submit the form with a deliberately bad email address and watch what happens.
If the only feedback is red text and a red border, the form communicates failure through color alone, which fails WCAG 1.4.1. Error text needs to say what is wrong in words, sit next to the field it describes, and be connected to that field with aria-describedby so assistive technology reads it on focus. Mark the field with aria-invalid="true". If the message appears without moving focus and without a live region, a screen reader user hears nothing at all and submits again.
Also confirm the success path. A form that silently clears itself after submission leaves the person unsure whether anything was sent.
The ten-minute pass
In order, on a real page:
- Click every caption. Does focus move into the field?
- Tab through the form. Can you reach and operate every control, in a sensible order, with a visible focus ring?
- Inspect each input. Does it have a correct
autocompletetoken and atypethat matches the data? - Open it in Safari on a phone. Does tapping a field zoom the page?
- Submit something invalid. Is the error in words, next to the field, and announced?
- Check the viewport meta tag for
user-scalable=no.
The accessibility checker in AcuityScan's free tools automates the parts with a definite right answer: inputs with no programmatic label, controls with no accessible name, color contrast below threshold, and missing form structure. It runs as one of more than 350 checks across 8 modules in the full site scan, which also verifies that the domain your form submits to can actually deliver the resulting notification email. A form that collects leads into a mailbox with broken authentication is its own failure mode, and the email configuration check covers that side.
Start with the field order. Labels first, then autocomplete, then types, then font size. Each one takes a single attribute or a single line of CSS, and the form that collects every lead you will ever get is worth four of them.
Scan your own site
See what 350+ checks find on your domain.
Free, no signup, 60 seconds. Email auth · DNS · SSL · Performance · SEO · Accessibility · Privacy · Mobile.
