Field
One form control with its label, an optional hint, and an error that shows itself when the control is invalid.
Example
View Code
<div class="field">
<label for="email">Email</label>
<input id="email" type="email" required aria-describedby="email-hint email-error">
<p id="email-hint" data-hint>We only use it to sign you in.</p>
<p id="email-error" data-error>Enter an address with an @ in it.</p>
</div>
When to use it
Every control in a form: text, email, number, select, textarea, checkbox, radio, switch, range. A form is a stack of fields and a button; the field owns what bare HTML cannot, the label's link to its control, the help text, and the error.
How it works
A tight column: label, control, hint, error. The control is a native element styled to the control tokens, so a theme that changes --yeti-control-radius changes every input. The error is hidden until the control is invalid and the visitor has touched it (:user-invalid), or until you set aria-invalid="true" after a server round trip; then it shows and the border turns to the alert colour. A required control gets a marker after its label. A checkbox or radio is laid out inline automatically, label after the control, and its checked mark is a variant-coloured centre inside a ring of the surface colour.
<fieldset class="field">
<legend>Notify me by</legend>
<div class="field"><input id="n-email" type="checkbox" name="notify" value="email"><label for="n-email">Email</label></div>
<div class="field"><input id="n-sms" type="checkbox" name="notify" value="sms"><label for="n-sms">Text message</label></div>
<p data-hint>Pick as many as you like.</p>
</fieldset>
A checkbox with role="switch" becomes a switch: a track with a thumb that slides to the end and takes the field's colour when on. A range input gets a thin track and a round thumb in the field's colour, the height of a control so it is easy to grab; the track is filled to --yeti-range-value, which CSS cannot work out for itself: set it inline for a static value, or from one line of your own script when the value moves.
<div class="field"><input id="dark" type="checkbox" role="switch"><label for="dark">Dark mode</label></div>
<div class="field"><label for="quality">Quality</label><input id="quality" type="range" min="0" max="100" value="70" style="--yeti-range-value: 70%"></div>
<div class="field"><label for="volume">Volume</label><input id="volume" type="range" min="0" max="100" value="40"></div>
The script form: const set = () => input.style.setProperty('--yeti-range-value', ((input.value - input.min) / (input.max - input.min) * 100) + '%'); input.addEventListener('input', set); set();.
Accessibility
The label must point at the control with for and the control must carry that id; Yeti's validator refuses an example without the pair. Put the hint's and the error's ids in the control's aria-describedby, so a screen reader hears the help text with the control and the error the moment it appears. Errors found on the server are shown with aria-invalid="true". The required marker is a visual echo of the required attribute, which is what is announced.
Attributes
| Attribute | Type | Values | Default | Description |
|---|---|---|---|---|
data-size |
enum | sm, md, lg |
md |
Scales the control's height and text. |
data-inline |
boolean | Put the label beside the control. Checkboxes and radios are inline without it. | ||
data-variant |
enum | primary, secondary, success, warning, alert, neutral |
primary |
The colour of a checked checkbox or radio. |
Markers
Attributes that descendants carry, not the root.
| Attribute | Type | Values | On | Description |
|---|---|---|---|---|
data-hint |
boolean | > * |
Help text, referenced by the control's aria-describedby. | |
data-error |
boolean | > * |
The error message, hidden until the control is invalid. |
Children
> label: 0 to 1. The label, with for pointing at the control's id. Required unless the field is a fieldset with a legend.> legend: 0 to 1. The legend, when the field is a fieldset grouping several controls.> input: 0 to 1. The control.> select: 0 to 1. The control.> textarea: 0 to 1. The control.> .affix: 0 to 1. The control slot as an affix: a control with attachments, or two controls joined.> [data-hint]: 0 to 1. Help text, referenced by the control's aria-describedby.> [data-error]: 0 to 1. The error message, hidden until the control is invalid.
Tokens
| Token | Description |
|---|---|
--yeti-field-gap |
Space between label, control, and hint. |
--yeti-control-size |
Minimum height of the control. |
--yeti-control-radius |
Corner of the control. |
--yeti-control-border |
Border of the control at rest. |
--yeti-range-value |
The filled share of a range's track; set it on the input. |
--yeti-control-surface |
Background of the control. |
--yeti-control-chevron |
The select's chevron image. |
--yeti-color-alert |
Border of an invalid control. |
--yeti-color-primary |
The default variant's colour, when data-variant is absent. |
--yeti-color-primary-subtle |
The default variant's tint. |
--yeti-color-primary-soft |
The default variant's soft stop. |
--yeti-color-primary-strong |
The default variant's strong stop. |
--yeti-color-primary-text |
The default variant's text colour. |
--yeti-on-primary |
Text on the default variant's colour. |
--yeti-text-md |
Text size when data-size is absent. |
--yeti-space-sm |
The space step when data-size is absent; a fieldset's padding follows it. |
--yeti-weight-strong |
Weight of the label or legend. |
--yeti-color-text |
Text of the control. |
--yeti-border-width |
Border width of every control, and of a fieldset. |
--yeti-duration-fast |
How long a control's border and a switch take to change. |
--yeti-ease |
The curve of that transition. |
--yeti-color-border-strong |
Border of a focused control. |
--yeti-radius-full |
Corners of the switch and of the range track. |
--yeti-space-xs |
Gap of an inline field, and a legend's inline padding. |
--yeti-text-sm |
Text size of the hint and the error. |
--yeti-color-text-muted |
The hint. |
--yeti-color-alert-text |
The error, and the required marker. |
--yeti-space-md |
Padding of a fieldset. |
Internal tokens (may change between minor versions)
- `--_yeti-variant` - `--_yeti-on-variant` - `--_yeti-size-text` - `--_yeti-size-space` - `--_yeti-variant-subtle` - `--_yeti-variant-soft` - `--_yeti-variant-strong` - `--_yeti-variant-text`Accessibility
- The label's for must match the control's id; the validator checks it. Reference the hint and the error from the control with aria-describedby so both are announced. Use aria-invalid="true" for errors found on the server. The required marker is decoration; the required attribute is what assistive tech reads. A switch is a checkbox with role="switch"; its label reads as the switch's name. A range needs a label like any control, and aria-valuetext when the numbers are not what a person would say.
Browser support
- Used without guards: :has(), :user-invalid, appearance: none, lh unit
- Behind
@supports: nothing
JavaScript
None. This component is CSS only.
Available since 7.0.0.