Examples
Checkbox and radio
<div class="cluster is-snug">
<input type="checkbox" checked class="input" />
<input type="checkbox" class="input" />
<input type="radio" name="demo-r" checked class="input" />
<input type="radio" name="demo-r" class="input" />
</div>
<div class="stack">
<label class="cluster is-snug">
<input type="checkbox" class="input" /> I agree to the terms and conditions
</label>
<fieldset class="stack is-snug">
<legend>Notification frequency</legend>
<label class="cluster is-snug">
<input type="radio" name="demo-freq" checked class="input" /> Immediately
</label>
<label class="cluster is-snug">
<input type="radio" name="demo-freq" class="input" /> Daily digest
</label>
<label class="cluster is-snug">
<input type="radio" name="demo-freq" class="input" /> Weekly digest
</label>
</fieldset>
</div>
<label class="media" style="--media-gap: var(--space-xs)">
<input type="checkbox" class="input media-figure" />
<span class="media-body"
>I agree to the Terms of Service, Privacy Policy, and Cookie Policy as described on
the legal page, including cross-site tracking consent where applicable in my
jurisdiction.</span
>
</label>
Toggle switch
<div class="cluster is-snug">
<input type="checkbox" role="switch" class="input" />
<input type="checkbox" role="switch" checked class="input" />
<input type="checkbox" role="switch" disabled class="input" />
<input type="checkbox" role="switch" checked disabled class="input" />
</div>
<div class="stack is-snug">
<label class="cluster is-snug">
<input type="checkbox" role="switch" checked class="input" /> Email notifications
</label>
<label class="cluster is-snug">
<input type="checkbox" role="switch" class="input" /> Push notifications
</label>
<label class="cluster is-snug">
<input type="checkbox" role="switch" class="input" /> SMS notifications
</label>
</div>
Source comments
Input family -- text inputs, textarea, select, file, checkbox,
radio, and input-group. Atoms share a common chrome token set
(--input-border-color, --input-border-width, --input-radius,
--input-bg, --input-focus-color, --input-transition) so one override
on any ancestor retones the whole family.
Markup:
<form class="stack">
<div class="stack is-tight">
<label for="email">Email</label>
<input id="email" type="email" class="input" required>
</div>
<button class="button" type="submit">Submit</button>
</form>
Labeled checkbox/radio: <label class="cluster is-tight">
(Flex's anon-item rule means no span wrapper around text.)
<fieldset> + <legend> for groups; bare with base.css defaults.
Design notes:
- Validation states paint borders; error COPY is author-
responsible (<p class="text-danger"> adjacent, or page-level
<div class="alert is-danger" role="alert">). The automatic
paint is gated by :user-invalid -- it matches only after the
user has interacted with the control, so an empty required
field does not render invalid on page load. Engines without
:user-invalid keep the aria-invalid paint (the author-driven
one) and simply skip the automatic one; graceful degradation,
no feature query (P-stance on modern CSS).
- A required field inside the field-unit stack (label directly
before the control) picks up a CSS-drawn marker on its label --
form.css owns that rule. The full label / help / error
convention lives in the patterns section's field unit page.
- Checkbox/radio/range use appearance:none custom chrome for
visual parity with .input in dense forms. @media (forced-
colors: active) reverts to native rendering for all three.
- Select chevron is a pure-CSS two-gradient V per P8. Border-
rotate chevron (details, sidebar-nav) needs a pseudo, and
<select> doesn't accept pseudos in evergreen browsers
without appearance: base-select.
- .input uses :focus (not :focus-visible) because text entry
needs the ring on click for caret visibility. Checkbox and
radio use :focus-visible (no caret).
- .input-group default: group owns border/bg; children are
transparent. .is-joined reinstates per-child borders for
the classic shaded-endcap look.
Reference
Source: src/css/input.css
Applies to
input[type="checkbox"].input, input[type="radio"].input
Selectors
| Selector | Description |
|---|---|
input[type="checkbox"][role="switch"].input | Toggle switch; renders as a sliding track and thumb instead of a box and tick |
Tokens
| Token | Default | Description |
|---|---|---|
--input-check-size | var(--ui-font-size-base) | Size of the checkbox or radio control |
--input-check-accent | var(--color-primary) | Accent color when checked |
--input-check-color | var(--color-on-primary) | Tick or dot color when checked |
--input-switch-track-width | 2.25rem | Width of the switch track |
--input-switch-track-height | 1.25rem | Height of the switch track |
--input-switch-thumb-offset | 2px | Inset offset for the thumb from the track edge |
--input-switch-thumb-size | calc( var(--input-switch-track-height) - var(--input-switch-thumb-offset) * 2 ) | Computed size of the switch thumb |
--input-switch-track-off | var(--color-border-stronger) | Track color in the off state |
--input-switch-track-on | var(--input-check-accent) | Track color in the on state |
--input-switch-thumb | var(--color-surface-float) | Thumb color |
Related: Input
The universal form-control class. One class covers every input type; each type shares the input appearance (border, radius, surface, focus ring) and adds its own shape below.
Source: src/css/input.css
Applies to
.input, .input-addon, .input-group, input[type="checkbox"].input, input[type="radio"].input
Classes
| Class | Kind | Description |
|---|---|---|
.is-sm | variant | Smaller text input with tighter padding |
.is-lg | variant | Larger text input with more padding |
Selectors
| Selector | Description |
|---|---|
input[type="file"].input | File input; padded shell around a styled native selector button |
textarea.input | Multi-line text; height comes from rows (or field-sizing), vertical resize only |
select.input | Native select; appearance:none with a CSS-drawn chevron |
Tokens
| Token | Default | Description |
|---|---|---|
--input-border-color | var(--color-border-stronger) | Border color shared across the input family |
--input-border-width | var(--border-width-default) | Border width shared across the input family |
--input-radius | var(--radius-md) | Border radius shared across the input family |
--input-bg | var(--color-surface) | Background color shared across the input family |
--input-focus-color | var(--color-focus) | Focus ring color shared across the input family |
--input-transition | var(--transition-fast) | Transition speed shared across the input family |
--input-height | 2.25rem | Block height for text inputs and select |
--input-padding-block | var(--ui-pad-block-compact) | Block-axis inner padding for text inputs and select |
--input-padding-inline | var(--ui-pad-inline-tight) | Inline-axis inner padding for text inputs and select |
--input-font-size | var(--ui-font-size-sm) | Font size for text inputs and select |
--input-line-height | var(--leading-tight) | Line height for text inputs and select |
--input-chevron-color | var(--color-text-muted) | Color of the select dropdown chevron |