📝 Form Design Principles
Forms can be particularly challenging for users with dyslexia, ADHD, and motor difficulties. Clear labels, helpful hints, and meaningful error messages are essential for accessible form design.
Design Guidelines
| Principle |
Description |
Recommendation |
| Clear Labels |
Associate labels with inputs |
Use <label> elements with for attribute |
| Input Hints |
Provide format guidance |
Show examples and format hints |
| Real-time Validation |
Validate as user types |
Don't wait until submission |
| Meaningful Errors |
Explain the problem |
Describe what's wrong and how to fix it |
| Autocomplete Support |
Enable browser fill |
Use correct autocomplete attributes |
| Appropriate Input Types |
Trigger right keyboard |
Use type="email", type="tel", etc. |
| Required Field Marking |
Indicate mandatory fields |
Use required attribute and visual markers |
| Focus Management |
Guide user to errors |
Auto-focus on first error field |
CSS Implementation
/* Form field styling */
.form-field {
margin-bottom: 1.5rem;
}
.form-label {
display: block;
font-weight: 600;
margin-bottom: 0.5rem;
}
.form-input {
width: 100%;
min-height: 44px;
padding: 0.75rem 1rem;
border: 2px solid #d1d5db;
border-radius: 0.5rem;
font-size: 1rem;
}
.form-input:focus {
outline: none;
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
}
/* Error state */
.form-input.error {
border-color: #ef4444;
}
.form-error {
color: #dc2626;
font-size: 0.875rem;
margin-top: 0.5rem;
}
/* Success state */
.form-input.success {
border-color: #22c55e;
}
Error Message Examples
<!-- Bad: Vague error message -->
<div class="error">输入有误,请检查</div>
<!-- Good: Specific and actionable error message -->
<div class="error" role="alert">
**手机号码格式不正确** 请输入11位手机号码,例如:13800138000
</div>
React Component
interface FormFieldProps {
label: string;
name: string;
type?: "text" | "email" | "tel" | "password" | "number";
placeholder?: string;
hint?: string;
required?: boolean;
error?: string;
success?: boolean;
autocomplete?: string;
}
export function FormField({
label,
name,
type = "text",
placeholder,
hint,
required = false,
error,
success,
autocomplete,
}: FormFieldProps) {
const [value, setValue] = useState("");
return (
<div className="form-control w-full">
<label className="label" htmlFor={name}>
<span className="label-text font-semibold">
{label}
{required && <span className="text-error ml-1">*</span>}
</span>
</label>
<div className="relative">
<input
id={name}
name={name}
type={type}
placeholder={placeholder}
required={required}
autoComplete={autocomplete}
value={value}
onChange={(e) => setValue(e.target.value)}
className={`
input input-bordered w-full min-h-[44px]
${error ? "input-error" : success ? "input-success" : ""}
`}
aria-invalid={!!error}
aria-describedby={
error ? `${name}-error` : hint ? `${name}-hint` : undefined
}
/>
{(error || success) && (
<span className="absolute right-3 top-1/2 -translate-y-1/2">
{error && <AlertCircle className="w-5 h-5 text-error" />}
{success && !error && (
<CheckCircle className="w-5 h-5 text-success" />
)}
</span>
)}
</div>
{hint && !error && (
<p id={`${name}-hint`} className="text-sm text-neutral-500 mt-1">
{hint}
</p>
)}
{error && (
<p
id={`${name}-error`}
className="text-sm text-error mt-1 flex items-center gap-1"
role="alert"
>
<AlertCircle className="w-4 h-4" />
{error}
</p>
)}
</div>
);
}
Autocomplete Attributes
| Field Type |
Autocomplete Value |
| Full Name |
name |
| Email |
email |
| Phone |
tel |
| Address |
street-address |
| City |
address-level2 |
| Postal Code |
postal-code |
| Country |
country |
| Credit Card |
cc-number |
Checklist
Related Resources