Core · Form fields
Field parts
What wraps a control: the label, the hint, the error and the group.
Label, hint and error
The text that names a control, says what it needs and says what went wrong.
Code
Copy the markup
.luz-field wraps the label, the control, the hint and the error. aria-describedby ties the hint and the error to the control:
<div class="luz-field">
<label class="luz-field__label luz-field__label--required" for="slug">Slug</label>
<input class="luz-input luz-input--error" id="slug" type="text" required aria-invalid="true" aria-describedby="slug-hint slug-error">
<div class="luz-field__helper" id="slug-hint">Letters, numbers and dashes.</div>
<div class="luz-field__error" id="slug-error"><span class="u-sr-only">Error: </span>Use letters, numbers and dashes only.</div>
</div>
Variants and options
.luz-field__label: the visible label.--requiredadds a red " *" after it..luz-field__helper: the hint, under the control..luz-field__error: the error, in the danger colour..luz-input--errorwitharia-invalid="true": a 2 px danger underline on the control.
How it works
The label names the control through for and id, and a click on it focuses the control. LUZ does not mark a field invalid for you: add the error class, aria-invalid and the message when your validation fails.
Without JavaScript
The label, the hint and the error are text in your HTML, so they show with no script. The browser still checks required and the type when the form is sent.
Keyboard and ARIA
- A label and a message take no focus and have no keys of their own.
- Write "Error: " before the error text, hidden with
.u-sr-onlyif you like, and list the hint and the error inaria-describedby.
Contrast and focus are in the Design tab.
Design
When to use
Use a label on every control, a hint when the reader needs the format or the reason, and an error after a check fails.
- The label always shows: it stays on screen while the reader types.
- The error goes beside the field it is about, in words.
When not to use
Do not swap one of these for another, and do not hide any of them.
- A placeholder is not a label: it disappears when the reader types.
- A colour or a border alone is not an error: say what is wrong. Do not show the error only in a toast: it goes away.
Do and don't
Writing the content
- The label is a short noun in sentence case: "Project name".
- The hint says the format or why you ask.
- The error says what is wrong and how to fix it. If you mark required fields with "*", say once, above the form, what it means.
Contrast and focus
Shared with the other field parts: contrast and focus of field parts.
Tokens it uses
Shared with the other field parts: tokens of field parts.
Keyboard and ARIA are in the Code tab.
Fieldset
A bordered group of related controls, named by its legend.
Code
Copy the markup
A native <fieldset> whose first child is a <legend>:
<fieldset class="luz-fieldset">
<legend>Shipping address</legend>
<div class="luz-field">
<label class="luz-field__label" for="street">Street</label>
<input class="luz-input" id="street" type="text">
</div>
<div class="luz-field">
<label class="luz-field__label" for="city">City</label>
<input class="luz-input" id="city" type="text">
</div>
</fieldset>
Variants and options
disabledon the fieldset disables every control inside it.role="group"witharia-labelledbyon a<div>names a group with no border, as the checkbox example does.
How it works
A native <fieldset> styled by components/form.css: a 1 px border, soft corners and the field background. The <legend> is small upper-case text.
Without JavaScript
Nothing changes: the fieldset and its legend are native and need no script.
Keyboard and ARIA
- A fieldset takes no focus; Tab moves through the controls inside it.
- The legend names the group: the browser exposes a fieldset as a group named by its legend.
Contrast and focus are in the Design tab.
Design
When to use
Use a fieldset for controls that answer one question together.
- A set of radio buttons or checkboxes, or an address.
- Put the legend first and keep it short.
When not to use
A fieldset is a group with a name, not a box for layout.
- A single control: its label is enough.
- Spacing or columns: the layout objects,
o-stackoro-grid. Do not wrap every section of a form.
Do and don't
Writing the content
- The legend is a noun or a question: "Shipping address", "Plan".
- No colon at the end: the style adds the space.
- Do not repeat the legend in each label.
Contrast and focus
Shared with the other field parts: contrast and focus of field parts.
Tokens it uses
Shared with the other field parts: tokens of field parts.
Keyboard and ARIA are in the Code tab.
Contrast and focus of field parts
The label and the hint are secondary text on the page; the error is danger text.
| Part | Colour on background | Light | Dark | High contrast | Needs |
|---|---|---|---|---|---|
Label | --luz-text-secondary on --luz-surface-page | 6.2:1 | 7.5:1 | 19.3:1 | 4.5:1 |
Hint | --luz-text-secondary on --luz-surface-page | 6.2:1 | 7.5:1 | 19.3:1 | 4.5:1 |
Error message | --luz-color-danger on --luz-surface-page | 5.3:1 | 11.7:1 | 9.3:1 | 4.5:1 |
Required asterisk | --luz-color-danger on --luz-surface-page | 5.3:1 | 11.7:1 | 9.3:1 | 4.5:1 |
Error border | --luz-color-danger on --luz-input-bg | 5.5:1 | 10.8:1 | 9.3:1 | 3:1 |
Legend | --luz-text-secondary on --luz-input-bg | 6.4:1 | 6.9:1 | 19.3:1 | 4.5:1 |
Measured from the token values of each mode, rounded down. Needs is the WCAG 2.2 AA minimum: 4.5:1 for text, 3:1 for focus rings, borders and icons.
- Focus: a label, a message and a legend take none; a click on a label moves focus to its control.
- Not colour alone: an invalid field has a 2 px bottom border and an error message in words.
- Target: a click on a label reaches its control.
Tokens of field parts
The 12 tokens that these controls' rules read, by token family. Each family links to its page, with the values in every mode.
- Spacing and sizing
--luz-space-2xs,--luz-space-lg,--luz-space-md,--luz-space-xs- Typography
--luz-font-sans,--luz-text-md,--luz-text-sm- Radius
--luz-radius-md
Known issues
None known.