form-design
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseForm Design
表单设计
Forms are where users give the product data. Every unnecessary obstacle between the user and a completed form is a failure. The design goal is to make correct input easy and incorrect input obvious — before the user submits.
表单是用户向产品提供数据的入口。用户与完成表单之间的任何不必要障碍都是设计失败。表单设计的目标是让正确输入变得容易,错误输入在用户提交前就能被明显识别。
The Three Guidance Layers
三层引导机制
Each layer serves a distinct purpose. Do not collapse them.
每一层都有明确的用途,请勿合并它们。
Layer 1 — Helper Text
第一层 — Helper Text
Explains what to enter. Appears below the input, always visible, in small secondary text.
Email address
[ ]
Use the email you signed up with.- Write in plain language from the user's perspective
- Keep it to one sentence — if you need more, the field is too complex or misnamed
- Do not repeat the label ("Enter your email" below a label that says "Email" is redundant)
- Helper text is not a replacement for a label — the label is still required
说明需要填写的内容。位于输入框下方,始终可见,使用小号次要文本显示。
Email address
[ ]
Use the email you signed up with.- 从用户视角使用平实语言撰写
- 控制在一句话以内——如果需要更多内容,说明该字段过于复杂或命名不当
- 不要重复标签内容(在“邮箱”标签下方写“输入你的邮箱”属于冗余)
- Helper Text不能替代标签——标签仍然是必填项
Layer 2 — Placeholder
第二层 — Placeholder
Shows the format or an example value. Appears inside the input, disappears on typing.
[jane@example.com ]- Use a realistic example, not a description: not
+358 40 123 4567Enter phone number - Never use placeholder as a label — it disappears and leaves the user without context
- Keep it grey () and lighter than actual input text
--color-text-secondary - Optional — not every field needs a placeholder
展示填写格式或示例值。位于输入框内部,用户开始输入后消失。
[jane@example.com ]- 使用真实示例,而非描述性文字:而非
+358 40 123 4567Enter phone number - 切勿将placeholder用作标签——它会消失,导致用户失去上下文参考
- 采用灰色(),颜色比实际输入文本浅
--color-text-secondary - 可选字段——并非所有字段都需要placeholder
Layer 3 — Validation
第三层 — Validation
Confirms whether the input is correct. The most important layer.
Email address
[jane@ ] ← invalid
✗ Enter a valid email address.Validation timing:
- On blur (leaving the field): default for most fields — validates once the user has finished
- Real-time (on input): use when the format is complex or the error is likely — password strength, IBAN, VAT number, URL, regex-heavy fields
- On submit: catches anything missed, scrolls to the first error
Real-time validation must be forgiving at the start — do not show an error the instant the user starts typing. Show it after a short debounce (300–500ms) or after the first character that makes the input definitively wrong.
确认输入内容是否正确。这是最重要的一层。
Email address
[jane@ ] ← invalid
✗ Enter a valid email address.校验时机:
- 失焦时(离开字段):大多数字段的默认方式——在用户完成输入后进行校验
- 实时校验(输入时):适用于格式复杂或容易出错的字段——密码强度、IBAN、增值税号、URL、正则匹配要求高的字段
- 提交时:捕捉所有遗漏的错误,滚动到第一个错误位置
实时校验在初始阶段必须具备容错性——不要在用户开始输入的瞬间就显示错误。应在短暂延迟(300–500ms)后,或在输入第一个明确导致内容无效的字符后再显示错误。
Submit Button State
提交按钮状态
The submit button enables when the form is valid. This is one of the clearest affordance signals in form design — the user sees the goal and knows when they have reached it.
[Submit] ← disabled, low contrast, cursor: not-allowed
(fields incomplete or invalid)
[Submit] ← enabled, full colour, cursor: pointer
(all required fields valid)Implementation:
html
<button type="submit" disabled={!isFormValid}>Submit</button>For long or complex forms where real-time validation is not practical, do not disable the submit — validate on submit and scroll to errors instead. Disabled submit on a long form frustrates users who cannot tell what is missing.
Loading state on submit: Replace label with spinner, disable the button. Prevent double-submission.
仅当表单验证通过时,提交按钮才启用。这是表单设计中最清晰的功能提示信号之一——用户能看到目标,并且知道自己何时达成目标。
[Submit] ← disabled, low contrast, cursor: not-allowed
(fields incomplete or invalid)
[Submit] ← enabled, full colour, cursor: pointer
(all required fields valid)实现方式:
html
<button type="submit" disabled={!isFormValid}>Submit</button>对于无法实现实时校验的长表单或复杂表单,不要禁用提交按钮——改为在提交时进行校验并滚动到错误位置。长表单禁用提交按钮会让用户因无法得知遗漏内容而感到沮丧。
提交时的加载状态: 将按钮文字替换为加载动画,禁用按钮。防止重复提交。
Field Anatomy
字段结构
[Label] [Optional badge if optional]
[Input field ]
[Helper text — what to enter, format, constraints ]
[Error message — appears below helper text on validation fail ]html
<div class="field">
<label for="vat">VAT number <span class="optional">Optional</span></label>
<input
id="vat"
type="text"
placeholder="FI12345678"
aria-describedby="vat-helper vat-error"
aria-invalid="true"
>
<p id="vat-helper" class="helper-text">Finnish VAT numbers start with FI followed by 8 digits.</p>
<p id="vat-error" class="error-text" role="alert">Enter a valid Finnish VAT number (e.g. FI12345678).</p>
</div>[Label] [Optional badge if optional]
[Input field ]
[Helper text — what to enter, format, constraints ]
[Error message — appears below helper text on validation fail ]html
<div class="field">
<label for="vat">VAT number <span class="optional">Optional</span></label>
<input
id="vat"
type="text"
placeholder="FI12345678"
aria-describedby="vat-helper vat-error"
aria-invalid="true"
>
<p id="vat-helper" class="helper-text">Finnish VAT numbers start with FI followed by 8 digits.</p>
<p id="vat-error" class="error-text" role="alert">Enter a valid Finnish VAT number (e.g. FI12345678).</p>
</div>Required vs Optional
必填与可选字段
Mark the minority. If most fields are required, mark the optional ones. If most are optional, mark the required ones.
- Do not rely on colour alone — add a text label ("Required" or asterisk with legend)
- Place the required/optional indicator in the label, not only in the placeholder or helper text
html
<label>Email <abbr title="Required">*</abbr></label>
<!-- or -->
<label>Phone <span class="badge">Optional</span></label>标记少数派字段。如果大多数字段为必填,则标记可选字段;如果大多数为可选,则标记必填字段。
- 不要仅依赖颜色区分——添加文本标签(“必填”或带说明的星号)
- 将必填/可选标记放在标签中,不要仅放在placeholder或helper text里
html
<label>Email <abbr title="Required">*</abbr></label>
<!-- or -->
<label>Phone <span class="badge">Optional</span></label>Grouping with Fieldset
使用Fieldset分组
Related fields belong in a with a . This is semantic HTML and helps screen readers announce the group context.
<fieldset><legend>html
<fieldset>
<legend>Billing address</legend>
<label>Street</label><input type="text">
<label>City</label><input type="text">
<label>Postal code</label><input type="text">
</fieldset>Use fieldsets for:
- Address groups
- Payment details
- Radio button groups
- Checkbox groups
相关字段应放在带有的中。这是语义化HTML,有助于屏幕阅读器播报分组上下文。
<legend><fieldset>html
<fieldset>
<legend>Billing address</legend>
<label>Street</label><input type="text">
<label>City</label><input type="text">
<label>Postal code</label><input type="text">
</fieldset>Fieldset适用于:
- 地址组
- 支付详情
- 单选按钮组
- 复选框组
Input Types
输入类型
Use the correct — browsers provide free validation, appropriate keyboards, and autofill.
type| Data | Input type |
|---|---|
| |
| Phone | |
| URL | |
| Number | |
| Password | |
| Date | |
| Search | |
| Colour | |
On mobile, shows the email keyboard, shows the numpad. These are free UX improvements.
type="email"type="tel"使用正确的属性——浏览器会提供免费的校验、合适的键盘和自动填充功能。
type| 数据类型 | 输入类型 |
|---|---|
| 邮箱 | |
| 电话 | |
| 网址 | |
| 数字 | |
| 密码 | |
| 日期 | |
| 搜索 | |
| 颜色 | |
在移动端,会显示邮箱键盘,会显示数字键盘。这些都是免费的用户体验优化。
type="email"type="tel"Autofill Support
自动填充支持
Allow browsers to autofill. Do not disable it unless there is a security requirement.
html
<input type="text" autocomplete="name">
<input type="email" autocomplete="email">
<input type="tel" autocomplete="tel">
<input type="text" autocomplete="street-address">
<input type="text" autocomplete="postal-code">
<input type="text" autocomplete="cc-number"> <!-- credit card -->
<input type="password" autocomplete="new-password">Correct values reduce friction dramatically for returning users and on mobile.
autocomplete允许浏览器自动填充。除非有安全要求,否则不要禁用该功能。
html
<input type="text" autocomplete="name">
<input type="email" autocomplete="email">
<input type="tel" autocomplete="tel">
<input type="text" autocomplete="street-address">
<input type="text" autocomplete="postal-code">
<input type="text" autocomplete="cc-number"> <!-- credit card -->
<input type="password" autocomplete="new-password">正确设置属性能显著减少回头用户和移动端用户的操作摩擦。
autocompleteReview Checklist
评审检查清单
- Every field has a visible label (not just placeholder)
- Helper text is below the input and explains what to enter
- Placeholder shows format or example, not a description
- Validation triggers on blur for simple fields, real-time for complex ones
- Error message is adjacent to the field that failed
- Error message is associated via
aria-describedby - Required/optional marked on the minority of fields
- Submit button is disabled when form is invalid (for short forms)
- Submit button shows a loading state and prevents re-submission
- Related fields are grouped in with
<fieldset><legend> - Correct attribute on all inputs
type - attributes set on address, contact, and payment fields
autocomplete
- 每个字段都有可见的标签(不只是placeholder)
- Helper Text位于输入框下方,说明填写内容
- Placeholder展示格式或示例,而非描述性文字
- 简单字段在失焦时触发校验,复杂字段采用实时校验
- 错误消息紧邻校验失败的字段
- 通过关联错误消息
aria-describedby - 在少数派字段上标记必填/可选
- 短表单在验证不通过时禁用提交按钮
- 提交按钮显示加载状态并防止重复提交
- 相关字段使用带的
<legend>分组<fieldset> - 所有输入框都设置了正确的属性
type - 地址、联系信息和支付字段设置了属性
autocomplete