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.