Build forms that users complete without confusion, anxiety, or abandonment. The goal is not to collect every possible field; it is to remove every unnecessary obstacle between the user and their goal.
Consult the form validation patterns reference for validation timing, error placement, multi-field dependencies, async validation, recovery design, conversion measurement, field-level drop-off, and field-by-field optimization guidance.
Consult the live validation UX reference for blur-vs-real-time timing, reward-early/punish-late behavior, and copy-paste-friendly validation.
Consult the error recovery reference for what happens after validation or submission fails.
Consult the disabled buttons UX reference when deciding whether to block submit buttons or keep them enabled with error explanation.
Consult the component anatomy reference for button, input, checkbox, radio, toggle, dropdown, and textarea anatomy guidance.
Consult the self-evident interface design reference when a form depends on too much helper text, instructions, or onboarding; prefer clearer grouping, defaults, constraints, examples, and inline feedback.
MANDATORY PREPARATION
Read frontend-design and follow its Context Gathering Protocol. Reuse available context and ask only about consequential gaps. Additionally gather: what goal the user is trying to achieve, which fields are truly required, and what causes abandonment in the current flow.
Assess Form Needs
Understand the form's purpose and context:
- User goal: What does the user get by completing this form? The clearer the payoff, the higher the completion rate.
- Field necessity: Every field you add drops completion rates. Challenge each field: is it required now, or can it be collected later?
- Context of use: Is the user rushed, distracted, using a compact viewport or coarse pointer, or in a stressful situation? Stressful contexts need simpler forms.
- Failure points: Where do users currently drop off? Long forms, unclear labels, and unexpected validation are common culprits.
- Data use: Which fields are actually used after submission? If sales, support, or onboarding does not use a field, remove it, infer it, or collect it later.
- Measurement: Do analytics show form views, first field focus, field completion, validation errors, submit attempts, successful submissions, and mobile vs desktop completion?
Form Structure
Field order
- Ask easy questions first to build momentum
- Group related fields visually (name fields together, address fields together)
- Place optional fields at the end or mark them clearly
- Separate billing and shipping only when they are genuinely different
Label design
- Use clear, scannable labels above the input (not inside as placeholder text)
- Sentence case is easier to read than Title Case
- Be specific: "Card number" not "Payment info"
- Helper text should explain format requirements, not repeat the label
- Before adding helper text, ask whether input type, width, placeholder example, prefix/suffix, default, or grouping can make the field self-evident
Input design
- Match input width to expected content (postal code fields should not be full-width)
- Use the appropriate input type (
type="email", type="tel", type="date") for better browser keyboards, autofill, and validation hints
- Show formatting hints as the user types (credit card spacing, phone number grouping)
- Autofill-friendly: use standard
name and autocomplete attributes
- Use field-specific affordances: email typo suggestions, phone country handling, searchable selects for long option lists, radio buttons for fewer than five choices, and expandable textareas for longer messages
- Normalize browser autofill visuals when custom input surfaces are dark, translucent, or heavily branded. Use Tailwind utilities for the normal field state first, then add a small CSS layer for browser pseudo-classes that Tailwind cannot express cleanly:
@import "tailwindcss";
@layer components {
.input:-webkit-autofill,
.input:-webkit-autofill:hover,
.input:-webkit-autofill:focus,
.input:-webkit-autofill:active {
border-color: color-mix(in oklab, white 40%, transparent);
caret-color: var(--color-white);
-webkit-text-fill-color: var(--color-white);
-webkit-box-shadow: 0 0 0 1000px color-mix(in oklab, white 20%, transparent) inset;
transition: background-color 5000s ease-in-out 0s;
}
.input:autofill {
border-color: color-mix(in oklab, white 40%, transparent);
caret-color: var(--color-white);
}
}
:-webkit-autofill covers Chromium and Safari. :autofill is the standards-facing selector for compatible browsers. Keep both, include hover/focus/active, and test actual saved-password and saved-address flows instead of trusting static screenshots.
Multi-step forms
Break long forms into steps when:
- There are more than 6-8 fields
- The form covers distinct topics (account info, payment, confirmation)
- Users need to review before final submission
Step design:
- Show progress ("Step 2 of 4") so users know what remains
- Allow navigation back to previous steps
- Preserve entered data if the user leaves and returns
- Validate each step before allowing progression, but do not block navigation backward
Conversion-sensitive forms
When a form captures a lead, demo request, quote request, application, or checkout intent:
- put the value proposition immediately above or beside the form
- state what happens after submit, including response time when relevant
- start with low-friction fields such as email or name before sensitive fields
- ask phone, company size, budget, or detailed requirements only when they materially improve follow-up
- use progressive profiling for returning users instead of asking everything up front
- add privacy assurance near sensitive fields, not buried in a footer
- offer alternative contact paths when the form is high intent, such as chat, email, phone, or calendar booking
Validation Strategy
Timing
- Validate on blur for clearly completed fields (email, phone, format-required fields)
- Validate on input only for immediate feedback that helps (password strength, character count)
- Validate on submit for everything else, especially cross-field dependencies
- Never validate a pristine field; it creates anxiety
Error design
- Place error messages directly below the field
- Explain what went wrong and how to fix it
- Use
aria-invalid and aria-describedby for screen reader association
- Preserve all user input when validation fails
- Move focus to the first error after failed submission
Success states
- Subtly confirm valid fields with a checkmark or green border
- Remove success indicators when the user edits the field again
- Do not celebrate every valid field; it becomes noise
Responsive Form UX
- Ensure coarse-pointer targets are at least 44×44px
- Use appropriate input types for optimized keyboards
- Minimize scrolling by breaking into steps or using progressive disclosure
- Show the numeric keyboard for number fields, email keyboard for email fields
- Avoid dropdowns for short lists; use radio buttons or segmented controls instead
Accessibility
- Associate every input with a label using
for/id
- Use
fieldset and legend for grouped fields
- Announce form-level errors with
role="alert" or aria-live="polite"
- Ensure error messages are programmatically associated with fields
- Test keyboard navigation through the entire form
- Do not rely on color alone for error indication
Anti-Patterns
- Too many fields: Every additional field reduces completion rates
- Placeholder as label: Disappears when the user types; bad for memory and accessibility
- Validate on load: Pristine fields showing errors feel accusatory
- Vague errors: "Invalid input" without explanation leaves users guessing
- Clearing fields on error: Losing typed data is deeply frustrating
- Disabled submit without guidance: A grayed-out button with no visible errors is a dead end
- Multi-step without progress indicator: Users do not know how much remains
- Inconsistent validation timing: Some on blur, some on submit, with no clear logic
- Ignoring input semantics: Using
type="text" for phone numbers prevents browsers from showing the best available keyboard and autofill behavior
- No save-and-resume: Long forms that cannot be saved mid-progress punish interruptions
Verify Form Quality
Before shipping:
1---2name: forms-163description: Design, structure, or improve form interfaces for clarity, completion rates, and user confidence. Use when the user asks to build a form, redesign a form flow, improve form conversion, add multi-step forms, fix form UX, or structure field layouts and validation.4---56Build forms that users complete without confusion, anxiety, or abandonment. The goal is not to collect every possible field; it is to remove every unnecessary obstacle between the user and their goal.78Consult the [form validation patterns](../frontend-design/reference/form-validation-patterns.md) reference for validation timing, error placement, multi-field dependencies, async validation, recovery design, conversion measurement, field-level drop-off, and field-by-field optimization guidance.9Consult the [live validation UX](../frontend-design/reference/live-validation-ux.md) reference for blur-vs-real-time timing, reward-early/punish-late behavior, and copy-paste-friendly validation.10Consult the [error recovery](../frontend-design/reference/error-recovery.md) reference for what happens after validation or submission fails.11Consult the [disabled buttons UX](../frontend-design/reference/disabled-buttons-ux.md) reference when deciding whether to block submit buttons or keep them enabled with error explanation.12Consult the [component anatomy](../frontend-design/reference/component-anatomy.md) reference for button, input, checkbox, radio, toggle, dropdown, and textarea anatomy guidance.13Consult the [self-evident interface design](../frontend-design/reference/self-evident-interface.md) reference when a form depends on too much helper text, instructions, or onboarding; prefer clearer grouping, defaults, constraints, examples, and inline feedback.1415## MANDATORY PREPARATION1617Read [frontend-design](../frontend-design/SKILL.md) and follow its Context Gathering Protocol. Reuse available context and ask only about consequential gaps. Additionally gather: what goal the user is trying to achieve, which fields are truly required, and what causes abandonment in the current flow.1819## Assess Form Needs2021Understand the form's purpose and context:22231. **User goal**: What does the user get by completing this form? The clearer the payoff, the higher the completion rate.242. **Field necessity**: Every field you add drops completion rates. Challenge each field: is it required now, or can it be collected later?253. **Context of use**: Is the user rushed, distracted, using a compact viewport or coarse pointer, or in a stressful situation? Stressful contexts need simpler forms.264. **Failure points**: Where do users currently drop off? Long forms, unclear labels, and unexpected validation are common culprits.275. **Data use**: Which fields are actually used after submission? If sales, support, or onboarding does not use a field, remove it, infer it, or collect it later.286. **Measurement**: Do analytics show form views, first field focus, field completion, validation errors, submit attempts, successful submissions, and mobile vs desktop completion?2930## Form Structure3132### Field order3334- Ask easy questions first to build momentum35- Group related fields visually (name fields together, address fields together)36- Place optional fields at the end or mark them clearly37- Separate billing and shipping only when they are genuinely different3839### Label design4041- Use clear, scannable labels above the input (not inside as placeholder text)42- Sentence case is easier to read than Title Case43- Be specific: "Card number" not "Payment info"44- Helper text should explain format requirements, not repeat the label45- Before adding helper text, ask whether input type, width, placeholder example, prefix/suffix, default, or grouping can make the field self-evident4647### Input design4849- Match input width to expected content (postal code fields should not be full-width)50- Use the appropriate input type (`type="email"`, `type="tel"`, `type="date"`) for better browser keyboards, autofill, and validation hints51- Show formatting hints as the user types (credit card spacing, phone number grouping)52- Autofill-friendly: use standard `name` and `autocomplete` attributes53- Use field-specific affordances: email typo suggestions, phone country handling, searchable selects for long option lists, radio buttons for fewer than five choices, and expandable textareas for longer messages54- Normalize browser autofill visuals when custom input surfaces are dark, translucent, or heavily branded. Use Tailwind utilities for the normal field state first, then add a small CSS layer for browser pseudo-classes that Tailwind cannot express cleanly:5556```css57@import "tailwindcss";5859@layer components {60 .input:-webkit-autofill,61 .input:-webkit-autofill:hover,62 .input:-webkit-autofill:focus,63 .input:-webkit-autofill:active {64 border-color: color-mix(in oklab, white 40%, transparent);65 caret-color: var(--color-white);66 -webkit-text-fill-color: var(--color-white);67 -webkit-box-shadow: 0 0 0 1000px color-mix(in oklab, white 20%, transparent) inset;68 transition: background-color 5000s ease-in-out 0s;69 }7071 .input:autofill {72 border-color: color-mix(in oklab, white 40%, transparent);73 caret-color: var(--color-white);74 }75}76```7778`:-webkit-autofill` covers Chromium and Safari. `:autofill` is the standards-facing selector for compatible browsers. Keep both, include hover/focus/active, and test actual saved-password and saved-address flows instead of trusting static screenshots.7980### Multi-step forms8182Break long forms into steps when:83- There are more than 6-8 fields84- The form covers distinct topics (account info, payment, confirmation)85- Users need to review before final submission8687**Step design**:88- Show progress ("Step 2 of 4") so users know what remains89- Allow navigation back to previous steps90- Preserve entered data if the user leaves and returns91- Validate each step before allowing progression, but do not block navigation backward9293### Conversion-sensitive forms9495When a form captures a lead, demo request, quote request, application, or checkout intent:9697- put the value proposition immediately above or beside the form98- state what happens after submit, including response time when relevant99- start with low-friction fields such as email or name before sensitive fields100- ask phone, company size, budget, or detailed requirements only when they materially improve follow-up101- use progressive profiling for returning users instead of asking everything up front102- add privacy assurance near sensitive fields, not buried in a footer103- offer alternative contact paths when the form is high intent, such as chat, email, phone, or calendar booking104105## Validation Strategy106107### Timing108109- Validate on blur for clearly completed fields (email, phone, format-required fields)110- Validate on input only for immediate feedback that helps (password strength, character count)111- Validate on submit for everything else, especially cross-field dependencies112- Never validate a pristine field; it creates anxiety113114### Error design115116- Place error messages directly below the field117- Explain what went wrong and how to fix it118- Use `aria-invalid` and `aria-describedby` for screen reader association119- Preserve all user input when validation fails120- Move focus to the first error after failed submission121122### Success states123124- Subtly confirm valid fields with a checkmark or green border125- Remove success indicators when the user edits the field again126- Do not celebrate every valid field; it becomes noise127128## Responsive Form UX129130- Ensure coarse-pointer targets are at least 44×44px131- Use appropriate input types for optimized keyboards132- Minimize scrolling by breaking into steps or using progressive disclosure133- Show the numeric keyboard for number fields, email keyboard for email fields134- Avoid dropdowns for short lists; use radio buttons or segmented controls instead135136## Accessibility137138- Associate every input with a label using `for`/`id`139- Use `fieldset` and `legend` for grouped fields140- Announce form-level errors with `role="alert"` or `aria-live="polite"`141- Ensure error messages are programmatically associated with fields142- Test keyboard navigation through the entire form143- Do not rely on color alone for error indication144145## Anti-Patterns146147- **Too many fields**: Every additional field reduces completion rates148- **Placeholder as label**: Disappears when the user types; bad for memory and accessibility149- **Validate on load**: Pristine fields showing errors feel accusatory150- **Vague errors**: "Invalid input" without explanation leaves users guessing151- **Clearing fields on error**: Losing typed data is deeply frustrating152- **Disabled submit without guidance**: A grayed-out button with no visible errors is a dead end153- **Multi-step without progress indicator**: Users do not know how much remains154- **Inconsistent validation timing**: Some on blur, some on submit, with no clear logic155- **Ignoring input semantics**: Using `type="text"` for phone numbers prevents browsers from showing the best available keyboard and autofill behavior156- **No save-and-resume**: Long forms that cannot be saved mid-progress punish interruptions157158## Verify Form Quality159160Before shipping:161162- [ ] Every field is justified; optional fields are clearly marked163- [ ] Labels are clear, specific, and above the input164- [ ] Validation does not trigger on pristine fields165- [ ] Errors explain what went wrong and how to fix it166- [ ] Input is preserved when validation fails167- [ ] Focus moves to the first error after failed submission168- [ ] Multi-step forms show progress and allow backward navigation169- [ ] Browser keyboards, autofill, and validation hints are optimized per field type170- [ ] The form is fully keyboard-navigable171- [ ] Color is not the only indicator of error or success