Skip to content

Switch <input>

Switches toggle a single setting on or off, taking effect immediately.

HTML tag<input>
Native
Progressive
Plain
Shadow-DOM
Native element
html
<l-form-field>
  <label>Email notifications</label>
  <input
    type="checkbox"
    role="switch"
    checked
  />
</l-form-field>

A switch is a native <input type="checkbox"> with role="switch" — keep the role so assistive tech announces "on/off" instead of "checked". l-form-field auto-styles a bare switch and wires the accessibility (label, hint, error, aria-*); standalone, apply .l-switch to the input yourself.

Use a switch for a setting that applies instantly (no Save step). For an option that only takes effect on form submission, prefer a checkbox.

Options

On

Native checked attribute.

Disabled

Native disabled attribute.

States

Code
html
<div class="flex flex-col gap-3">
  <l-form-field>
    <label>Off</label>
    <input
      type="checkbox"
      role="switch"
    />
  </l-form-field>
  <l-form-field>
    <label>On</label>
    <input
      type="checkbox"
      role="switch"
      checked
    />
  </l-form-field>
  <l-form-field>
    <label>Disabled</label>
    <input
      type="checkbox"
      role="switch"
      disabled
    />
  </l-form-field>
  <l-form-field>
    <label>Disabled on</label>
    <input
      type="checkbox"
      role="switch"
      checked
      disabled
    />
  </l-form-field>
  <l-form-field invalid>
    <label>Invalid (required, off)</label>
    <input
      type="checkbox"
      role="switch"
      required
    />
  </l-form-field>
</div>

Invalid

Styled via :user-invalid (after interaction) or by setting aria-invalid="true". Inside l-form-field this is managed for you.

Size & accent

Override --size for the track height (the whole control scales from it) and --accent for the on fill.

Code
html
<div class="flex flex-col gap-3">
  <l-form-field>
    <label>Default</label>
    <input
      type="checkbox"
      role="switch"
      checked
    />
  </l-form-field>
  <l-form-field>
    <label>Large</label>
    <input
      type="checkbox"
      role="switch"
      class="[--size:1.5rem]"
      checked
    />
  </l-form-field>
  <l-form-field>
    <label>Extra large, dark accent</label>
    <input
      type="checkbox"
      role="switch"
      class="[--size:2rem] [--accent:var(--l-color-gray-900)]"
      checked
    />
  </l-form-field>
</div>

Examples

With a hint

l-form-field wires the accessibility (label, hint, aria-*).

We'll only email you about account activity.

Code
html
<l-form-field>
  <label>Email notifications</label>
  <input
    type="checkbox"
    role="switch"
    checked
  />
  <p class="l-hint">We'll only email you about account activity.</p>
</l-form-field>

Right-to-left

In a dir="rtl" context the thumb rests at the inline-start (right) and slides to the inline-end (left) when on — no extra markup needed.

سنراسلك فقط بشأن نشاط حسابك.

Code
html
<div dir="rtl">
  <l-form-field>
    <label>إشعارات البريد الإلكتروني</label>
    <input
      type="checkbox"
      role="switch"
      checked
    />
    <p class="l-hint">سنراسلك فقط بشأن نشاط حسابك.</p>
  </l-form-field>
</div>

Accessibility

Criteria

Role

Native <input type=checkbox> plus role=switch — exposes the switch role with an on/off state

WCAG4.1.2
RGAA11.1
Accessible name

Pair the switch with a <label> (wrap the input or use for/id)

WCAG1.3.1
RGAA11.1
State, not color

On/off is conveyed by the thumb position and the checked state, not by color alone

WCAG1.4.1
RGAA3.1
Target size

The label is part of the click target; keep the interactive area at least 24×24px

WCAG2.5.8
Focus visible

Keyboard focus shows a 2px outline via :focus-visible

WCAG2.4.7
RGAA10.7
Reduced motion

The slide and squish animations collapse to 0ms under prefers-reduced-motion

WCAG2.3.3
High contrast

In forced-colors mode the track gains a system-color outline and the on state switches it to Highlight

WCAG1.4.11

Rules

  • Always add role='switch' to the <input type='checkbox'> — the skin and the inline field layout depend on it
  • Always pair the switch with a <label> — wrap the input or link with for/id
  • Use a switch only for settings that apply immediately; use a checkbox when the change is committed on submit
  • Write the label as the thing being turned on (e.g. Email notifications), not an instruction

Keyboard interactions

Tab
Moves focus to the switch
Space
Toggles the switch on or off

API reference

Importing

css
@import 'luxen-ui/css/switch';

Attributes & Properties

roleAttribute
Must be switch. Promotes the native checkbox to a switch for assistive tech and triggers the switch skin / inline field layout.
checkedAttribute
Whether the switch is on.
disabledAttribute
Disables the switch.
requiredAttribute
Marks the switch as required for form submission.
aria-invalidAttribute
Set to true to force the invalid style (otherwise applied via :user-invalid). l-form-field manages this automatically.

CSS classes

.l-switchClass
Base switch style, applied to <input type="checkbox" role="switch">. The role="switch" is required so assistive tech announces "on/off" (not "checked") and l-form-field lays it out inline. Inside l-form-field a bare switch is auto-styled, so the class is optional there.

CSS custom properties

--sizedefault:1.25emCustom property
Track height; the whole control scales from it.
--accentdefault:var(--l-form-control-activated-color)Custom property
Track fill when on.