Beware of the Leopard — Part 1: Asking the right question
Table of contents
Asking the right questions
You remember the scene from The Hitchhiker's Guide to the Galaxy? Arthur Dent discovers his house is about to be demolished. He protests — nobody told him. He's informed the plans were "on display." Where? In the bottom of a locked filing cabinet, stuck in a disused lavatory, with a sign on the door saying "Beware of the Leopard." The information was technically available — but practically inaccessible.
Replace the filing cabinet with form fields, the locked door with missing labels, the disused lavatory with an incoherent tab order, and "Beware of the Leopard" with a generic "Error" message. You've just described the experience of millions of users facing web forms.
A form is a conversation. Each field asks a question, each validation listens to the answer, each error message guides toward the right one. When this conversation breaks down, silent questions, ignored answers, incomprehensible corrections, the user goes in circles. Just like Arthur Dent looking for that filing cabinet.
This first article covers the foundations: how to ask the right questions. The next one will handle listening to the answers.
The cost of silence
Forms are the last obstacle before conversion. Sign-up, purchase, contact, application. Every time, a form. And every time, users who give up.
According to the WebAIM Million 2026 report, 33.1% of form fields on the web aren't properly labeled. One third. The Baymard Institute measures a global cart abandonment rate of 70.19%, aggregated across 49 studies, tracked for 14 years. 18% of these abandonments are due to a process that's too long or too complicated, and the average checkout contains 23 form elements when the ideal is 12. Fixing these usability issues can increase conversions by 35%.
In Europe, a ContentSquare Foundation study on e-commerce in 2025 echoes this: forms show a 68% average failure rate, due to missing labels, autocomplete, and error indication.
This isn't an isolated accessibility problem. It's a design problem that affects everyone. And costs money on every visit. Users of assistive technologies are impacted first, but a poorly designed form also frustrates the mobile user fighting an inadequate keyboard, the rushed user who doesn't understand what's being asked, and the cautious user who abandons at the first incomprehensible error message.
The label is the question
A form field without a label is a counter without a sign. The field is there, the cursor blinks, but nobody says what it expects.
The <label> does three things at once:
- It tells assistive technology what the field expects. Without a label, the screen reader just announces "edit field, blank"
- It enlarges the click area. Clicking the label text activates the field, which helps users with motor difficulties
- It stays visible during input, unlike the placeholder
That last point is crucial. The placeholder is not a label:
<!-- Don't do this -->
<input type="email" placeholder="Email address">
<!-- Do this -->
<label for="email">Email address</label>
<input id="email" type="email" placeholder="e.g. name@domain.com">The placeholder disappears as soon as the user starts typing. If it's your only indication, the user no longer knows what was asked after the first character. And for screen readers, the placeholder isn't reliably announced. Support varies across browser/assistive technology combinations.
The <label> + <input> association is made through the for attribute pointing to the field's id. It's an explicit, verifiable link that every assistive technology understands unambiguously.
Guiding before input
The label says what. The field's attributes say how.
The right field type
<input type="text"> <!-- generic — no keyboard hint -->
<input type="email"> <!-- @ key on mobile keyboard -->
<input type="tel"> <!-- numeric keypad, phone semantics -->
<input type="url"> <!-- .com key, / key on mobile -->
<input type="number"> <!-- quantities only, no leading zeros -->
<input type="search"> <!-- search styling, clear button -->Each type adapts the keyboard on mobile and informs the screen reader of the expected format; some (email, url, number) also activate native validation. Using type="text" everywhere forces the user to type an email address on a keyboard that offers neither the @ nor the .com.
Watch out for type="number": it adds a stepper (up/down arrows) and strips leading zeros. It's appropriate for quantities (number of items, number of participants), not for numeric identifiers (postal code, phone number, credit card). And type="tel" has phone number semantics. The screen reader announces it as such. Don't use it as a shortcut to get a numeric keypad.
The right keyboard on mobile
When type isn't enough, inputmode takes over:
<!-- A postal code: numeric input -->
<input type="text" inputmode="numeric" pattern="[0-9]*">inputmode controls the keyboard displayed on mobile without changing the field's semantics. It's the clean solution for postal codes, verification codes, social security numbers. Numeric fields that are neither quantities nor phone numbers.
The browser already knows
The autocomplete attribute is probably the most underused in HTML. It tells the browser what type of data the field expects, and the browser fills it in automatically if the user has entered it elsewhere.
<label for="name">Full name</label>
<input id="name" type="text" autocomplete="name">
<label for="email">Email address</label>
<input id="email" type="email" autocomplete="email">
<label for="tel">Phone</label>
<input id="tel" type="tel" autocomplete="tel">
<label for="address">Address</label>
<input id="address" type="text" autocomplete="street-address">On mobile, this transforms a 2-minute form into 10 seconds of validation. For users with motor difficulties, it's the difference between a fillable form and an abandoned one.
The full list of autocomplete values covers name, email, phone, address, credit card, date of birth, and much more.
Group to clarify
When a form exceeds 3-4 fields, structure becomes as important as individual labels. That's the role of <fieldset> and <legend>. Grouping related fields and giving the group a title.
<fieldset>
<legend>Shipping address</legend>
<label for="street">Street</label>
<input id="street" type="text" autocomplete="shipping street-address">
<label for="city">City</label>
<input id="city" type="text" autocomplete="shipping address-level2">
<label for="zip">Postal code</label>
<input id="zip" type="text" inputmode="numeric" autocomplete="shipping postal-code">
</fieldset>
<fieldset>
<legend>Billing address</legend>
<!-- same fields, different autocomplete prefix: "billing" -->
</fieldset>Without <fieldset>, a screen reader announces "Street, edit field", but the user doesn't know if it's the shipping or billing street. With <fieldset> and <legend>, it announces "Shipping address, Street, edit field." Context is immediate.
And the legend must be relevant. "Information" says nothing. "Shipping address" says everything. A vague legend is a road sign pointing in every direction.
The label, meanwhile, must be visually adjacent to its field — above or to the left in Western reading order. A label at the other end of the line, or separated by a decorative element, is a guessing game for everyone. And for a user zooming at 200%, the distance multiplies.
The same principle applies to radio button and checkbox groups:
<fieldset>
<legend>Shipping method</legend>
<label>
<input type="radio" name="shipping" value="standard">
Standard (3-5 days)
</label>
<label>
<input type="radio" name="shipping" value="express">
Express (24h)
</label>
</fieldset>Without the <fieldset>, the screen reader announces "Standard 3-5 days, radio button". The user doesn't know what they're choosing the method of. With the <fieldset>, it announces "Shipping method, Standard 3-5 days, radio button." One sentence, full context.
For long dropdown lists, <optgroup> does the same job as <fieldset> does for fields: it structures options into named groups.
<label for="country">Country</label>
<select id="country" autocomplete="country">
<optgroup label="Europe">
<option value="FR">France</option>
<option value="DE">Germany</option>
<option value="ES">Spain</option>
</optgroup>
<optgroup label="North America">
<option value="US">United States</option>
<option value="CA">Canada</option>
</optgroup>
</select>The screen reader announces "Europe, France" instead of leaving the user to guess through a 50-country menu with no landmarks. Without <optgroup>, a long list is a linear soup — exactly the same problem as div soup.
The overall criteria
WCAG covers form labeling and structure through several criteria:
- 1.3.1 Info and Relationships — relationships between labels, fields, and groups are programmatically determinable (Level A)
- 1.3.5 Identify Input Purpose — the purpose of each personal data field is identifiable via the
autocompleteattribute (Level AA) - 2.5.3 Label in Name — the field's accessible name contains the visible label text (Level A)
- 3.3.2 Labels or Instructions — labels or instructions are provided for fields that expect input (Level A)
WCAG 2.1 AA is the technical standard referenced, directly or indirectly, by accessibility legislation worldwide — the ADA in the US, the Equality Act in the UK, the EAA in Europe, the ACA in Canada.
Part 2 will cover validation, errors, and correction criteria. Part 3 will cover multi-step forms.