Field
Input, select, textarea, checkbox and radio. One control for the 34 files that each style their own today.
Text, select and textarea
HTML
<div style="max-width:26rem">
<label class="p234-field">
<span class="p234-field__label">Email address</span>
<input class="p234-field__control" type="email" placeholder="you@example.com" autocomplete="email">
</label>
<label class="p234-field">
<span class="p234-field__label">State</span>
<p class="p234-field__hint">Prices are published for all 36 states and the FCT.</p>
<select class="p234-field__control">
<option>Lagos</option><option>Abuja</option><option>Kano</option><option>Rivers</option>
</select>
</label>
<label class="p234-field">
<span class="p234-field__label">What went wrong? <span class="p234-field__optional">(optional)</span></span>
<textarea class="p234-field__control" placeholder="Tell us what you expected to see"></textarea>
</label>
</div>Invalid
The border changes colour and thickens, and the message sits under the field in text. Three signals, so the state survives colour blindness and a washed-out screen.
Invalid field
HTML
<div style="max-width:26rem">
<label class="p234-field">
<span class="p234-field__label">Email address</span>
<input class="p234-field__control" type="email" value="not-an-address" aria-invalid="true" aria-describedby="f-err">
<p id="f-err" class="p234-field__error">Enter an email address in the form you@example.com</p>
</label>
</div>Disabled
HTML
<div style="max-width:26rem">
<label class="p234-field">
<span class="p234-field__label">Country</span>
<input class="p234-field__control" value="Nigeria" disabled>
</label>
</div>Checkbox and radio
The whole row is the target, not just the box. On a phone a 20px box is a miss waiting to happen.
Checkbox with a hint, and a radio group
HTML
<div style="max-width:30rem">
<label class="p234-check">
<input type="checkbox">
<span class="p234-check__text">
I agree to the Terms
<span class="p234-check__hint">Required before we can send you product updates.</span>
</span>
</label>
<fieldset style="border:0;padding:0;margin:var(--p234-space-5) 0 0">
<legend class="p234-field__label" style="padding:0">How often?</legend>
<label class="p234-check"><input type="radio" name="freq" checked><span class="p234-check__text">Every weekday</span></label>
<label class="p234-check"><input type="radio" name="freq"><span class="p234-check__text">Weekly summary</span></label>
<label class="p234-check"><input type="radio" name="freq"><span class="p234-check__text">Only when something changes</span></label>
</fieldset>
</div>Rules
- Every control has a real label. A placeholder disappears exactly when the reader needs it.
- Mark optional fields, not required ones. On most of our forms nearly everything is required, so marking the exception is less noise.
- Put the hint above the control, where it is read before the typing starts, not after.
- Use
aria-invalidand point at the message witharia-describedby. - Say what to do: "Enter an email address in the form you@example.com", not "Invalid input".
- Do not validate on every keystroke. Validate when the field is left, and again on submit.
- Do not shrink a control below 44px to fit a layout. Change the layout.
- Do not restyle the checkbox into a custom shape. The native control is accessible, familiar and free; it only needs
accent-color.
Submitting
On a failed submit, move focus to the first invalid field and summarise what to fix above the form. A reader on a phone may not be able to see the field that failed.
Tokens this component reads
--p234-color-ink--p234-color-ink-muted--p234-color-error--p234-color-brand--p234-color-field-bg--p234-color-field-border--p234-color-field-border-hover--p234-color-field-ink-placeholder--p234-color-field-bg-disabled--p234-field-height--p234-field-padding-x--p234-field-radius--p234-field-border-width--p234-field-border-width-invalid--p234-type-ui-*--p234-type-meta-*