Menu


Switch


An on-or-off control that takes effect at once: a filled track with a light thumb that slides to the on side.

Customize the preview


Choices
Show
View

Options


Switch options
ChoiceValuesDefaultWhat it does
sizesmbk-switch--size-<value>lgmdsmlg
The track 24, 20 or 16 tall, with its thumb. The small thumb has no room for the tick or the cross.

Partssmbk-switch__controlsmbk-switch__tracksmbk-switch__thumbsmbk-switch__on-iconsmbk-switch__off-iconsmbk-switch__label

Examples


Usage

An on/off control with its label.

States

Off and on: the filled gray track, and the red one.

With icon

A tick on the thumb when on and a cross when off, on the large and medium sizes.

Disabled

Dimmed, in both states.

Sizes

Three sizes.

Guidelines


Purpose

An on-or-off setting that takes effect the moment it is flipped, like a light switch. The thumb's position says the state; the brand fill says it is on, the gray fill that it is off. A checkbox is for a choice saved later; a switch is for a change made now.

When to use

  • Settings and preferences that apply immediately.
  • Turning a feature on or off in a panel.

When not to use

  • Anything submitted with a form. Use a checkbox.
  • Choosing between two named options. Use the segmented control, which shows both names.

Usage rules

Do

  • Label the setting, not the action: "Notifications", not "Turn on notifications".

Don't

  • Ask for confirmation after a switch. If a change needs confirming, it is not a switch.
Do

Label the setting, not the action, so the label stays true whether the switch is on or off.

Don't

An action as the label reads wrong half the time, like "Turn on" beside a switch that is already on.

Anatomy

  • The block, a label element holding everything.
  • The control part, the real checkbox with the switch role, visually hidden.
  • The track part, the rounded channel, filled gray when off and red when on.
  • The thumb part, the raised light square that sits at one end or the other. It stays light in both themes.
  • The on-icon and off-icon parts, optional: a tick on the thumb when on and a cross when off, on the lg and md sizes.
  • The label part, the text.

Behavior

Flipping slides the thumb to the other end with the state motion, the same in both directions, and swaps the track fill at once, so a theme change never fades it. Under reduced motion the thumb jumps. Under the pointer, an on track darkens its red; an off track stays as it is. With a mouse, pointing at the switch stretches the thumb a little wider, like a pill, and pressing it stretches the thumb further and squashes it, so the switch answers the press before it flips. Off, the thumb grows from its start; on, it grows inward, so its outer edge stays at the end of the track. The switch itself and everything around it never move. A disabled switch and a touch screen do not stretch, and under reduced motion the stretch changes at once. Disabled turns the track a faint gray, the thumb the disabled surface without its edge or lift.

With icon, the thumb carries a tick when on and a cross when off. The small thumb has no room for them, so the small size never shows them.

Three sizes: lg, a 24 track; md, 20; sm, 16. At every size the whole row is at least 24 tall.

On a touch screen the row keeps its height and takes an invisible press area out to the comfortable touch target; between switches stacked one under another it reaches only halfway into the gap.

Accessibility


What it does for you

  • The control carries the switch role, so it is announced as a switch with on and off, and Space flips it.
  • The label element names it; the text is required.
  • The focus ring draws around the track.
  • State is shown by position and fill, not by color alone.
  • The tick and the cross are hidden from assistive technology, which hears the state from the control.
  • On a touch screen the row keeps its height and takes an invisible press area out to the comfortable touch target.

What you must do

  • Give every switch label text, which names it.

How to test

  • Tab to the switch: the focus ring shows around the track, in both themes and in a forced-color mode. Press Space: it flips.
  • With a screen reader, it is read as a switch by its label, on or off.
  • On a touch screen, a press just outside the track still flips it.
  • With text at 200% and the page 320 pixels wide, the label stays whole beside the track.

Keyboard

Switch keys
KeyWhat it does
Tab
Moves focus to the switch. A disabled switch is skipped.
Space
Flips the switch.

Source


The files the switch is made of. Its folder on GitHub (opens in a new tab) holds them with its wrapper and its document.

Stylesheet
switch.css
/* smbk-switch — Switch. Figma "Switch" 4086:11238 (Size × State × Checked, with an Icon boolean).
 * The track is two thumbs wide plus its inset, so the thumb slides exactly
 * one thumb-width to the on side: its own width, so no distance is written.
 * The off track is filled, so the switch shows against any page without an edge.
 * The thumb stays light in both themes and may carry a tick when on and a cross when off.
 * --smbk-switch-thumb is the thumb's resting size at each size; the thumb's own width and height start from it and
 * stretch while it is pointed at or pressed (motion, below). */

.smbk-switch {
  --smbk-switch-thumb: var(--smbk-size-selection-md);
}

/* .smbk-switch__control: hidden from view, kept for screen readers and the keyboard, by the shared rule in visually-hidden/visually-hidden.css.
   The row, its type, the disabled colour, the focus ring on the track and the touch area are shared
   with the other choices, in choice/choice.css; this sheet draws the track. */

.smbk-switch__track {
  box-sizing: border-box;
  display: inline-flex;
  align-items: center;
  justify-content: flex-start;
  flex-shrink: 0;
  width: calc(2 * var(--smbk-size-selection-md) + 2 * var(--smbk-space-inset-2xs));
  height: var(--smbk-size-selection-lg);
  padding: var(--smbk-space-inset-2xs);
  border-radius: var(--smbk-radius-control-sm);
  background: var(--smbk-color-surface-track);
}

/* The thumb's two marks share its one cell; the state shows one of them. */
.smbk-switch__thumb {
  box-sizing: border-box;
  --smbk-switch-thumb-width: var(--smbk-switch-thumb);
  --smbk-switch-thumb-height: var(--smbk-switch-thumb);
  display: grid;
  place-items: center;
  width: var(--smbk-switch-thumb-width);
  height: var(--smbk-switch-thumb-height);
  border: var(--smbk-border-width-hairline) solid var(--smbk-color-border-groove-bottom);
  border-radius: var(--smbk-radius-inset);
  background: var(--smbk-color-surface-thumb);
  box-shadow: var(--smbk-elevation-raised);
}

.smbk-switch__on-icon,
.smbk-switch__off-icon {
  grid-area: 1 / 1;
  color: var(--smbk-color-icon-on-thumb);
  font-size: var(--smbk-size-icon-xs);
}

.smbk-switch__on-icon,
.smbk-switch__control:checked + .smbk-switch__track .smbk-switch__off-icon {
  visibility: hidden;
}

.smbk-switch__control:checked + .smbk-switch__track .smbk-switch__on-icon {
  visibility: visible;
}

.smbk-switch__control:checked + .smbk-switch__track {
  background: var(--smbk-color-surface-brand);
}

/* Hover: an on track darkens its red; an off track stays as it is. */
@media (hover: hover) {
  .smbk-switch:hover .smbk-switch__control:enabled:checked + .smbk-switch__track {
    background: var(--smbk-color-action-brand-background-hover);
  }
}

/* On, the thumb's outer edge sits at the track's far end, two resting thumbs in: a thumb stretched wider than at
   rest grows toward the inside, so that edge stays where it is. */
.smbk-switch__control:checked + .smbk-switch__track .smbk-switch__thumb {
  translate: calc(2 * var(--smbk-switch-thumb) - var(--smbk-switch-thumb-width)) 0;
}

.smbk-switch__control:checked + .smbk-switch__track .smbk-switch__thumb:dir(rtl) {
  translate: calc(var(--smbk-switch-thumb-width) - 2 * var(--smbk-switch-thumb)) 0;
}

.smbk-switch__control:disabled + .smbk-switch__track {
  background: var(--smbk-color-surface-track-subtle);
}

.smbk-switch__control:disabled + .smbk-switch__track .smbk-switch__thumb {
  border-color: transparent;
  background: var(--smbk-color-surface-disabled);
  box-shadow: none;
}

.smbk-switch__control:disabled + .smbk-switch__track :is(.smbk-switch__on-icon, .smbk-switch__off-icon) {
  color: var(--smbk-color-icon-disabled);
}

/* ---- sizes ---- */

.smbk-switch--size-md .smbk-switch__track {
  width: calc(2 * var(--smbk-size-selection-sm) + 2 * var(--smbk-space-inset-2xs));
  height: var(--smbk-size-selection-md);
}

.smbk-switch--size-md {
  --smbk-switch-thumb: var(--smbk-size-selection-sm);
}

.smbk-switch--size-sm .smbk-switch__track {
  width: calc(2 * var(--smbk-size-12) + 2 * var(--smbk-space-inset-2xs));
  height: var(--smbk-size-selection-sm);
}

.smbk-switch--size-sm {
  --smbk-switch-thumb: var(--smbk-size-12);
}

/* The small thumb has no room for a mark. */
.smbk-switch--size-sm :is(.smbk-switch__on-icon, .smbk-switch__off-icon) {
  display: none;
}

/* ---- motion: the thumb slides across with the state purpose, the same way in both directions.
   The track's color changes at once, so a theme change never fades. With a mouse, pointing at the switch
   stretches the thumb a small step wider, into a pill; pressing stretches it a step more and squashes it as much,
   centred in the track (the small switch, whose thumb is tiny, squashes by the small step only). Off, the thumb
   grows from its start edge; on, toward the inside, so its outer edge stays at the track's end. The stretch
   moves with the state purpose. The box, the track and what is around the switch never move; a disabled
   switch and a touch screen do not stretch. Under reduced motion the thumb jumps and its size changes at once. ---- */

.smbk-switch__thumb {
  transition-property: translate, width, height;
  transition-duration: var(--smbk-motion-state-duration);
  transition-timing-function: var(--smbk-motion-state-easing);
}

@media (hover: hover) {
  .smbk-switch:hover .smbk-switch__control:enabled + .smbk-switch__track .smbk-switch__thumb {
    --smbk-switch-thumb-width: calc(var(--smbk-switch-thumb) + var(--smbk-space-2));
  }

  .smbk-switch:active .smbk-switch__control:enabled + .smbk-switch__track .smbk-switch__thumb {
    --smbk-switch-thumb-width: calc(var(--smbk-switch-thumb) + var(--smbk-space-4));
    --smbk-switch-thumb-height: calc(var(--smbk-switch-thumb) - var(--smbk-space-4));
  }

  .smbk-switch--size-sm:active .smbk-switch__control:enabled + .smbk-switch__track .smbk-switch__thumb {
    --smbk-switch-thumb-height: calc(var(--smbk-switch-thumb) - var(--smbk-space-2));
  }
}

@media (prefers-reduced-motion: reduce) {
  .smbk-switch__thumb {
    transition: none;
  }
}

/* ---- high contrast (forced colors) ---- */
/* In Windows high-contrast mode the browser drops fills and shadows; this puts the meaning back with the
   user's own colors. Nothing here applies outside that mode. */

@media (forced-colors: active) {
  /* Off: the fill is dropped, so the track takes an edge in the text color. */
  .smbk-switch__track {
    outline: var(--smbk-border-width-hairline) solid CanvasText;
  }

  /* On: the track filled with Highlight and edged in it, the thumb in HighlightText at the far end. */
  .smbk-switch__control:checked + .smbk-switch__track {
    background: Highlight;
    outline: var(--smbk-border-width-hairline) solid Highlight;
  }

  .smbk-switch__control:checked + .smbk-switch__track .smbk-switch__thumb {
    border-color: HighlightText;
    background: HighlightText;
  }

  .smbk-switch__control:checked + .smbk-switch__track .smbk-switch__on-icon {
    color: Highlight;
  }

  /* Disabled: the track keeps an edge, in GrayText; on, it is filled with GrayText. */
  .smbk-switch__control:disabled + .smbk-switch__track {
    outline: var(--smbk-border-width-hairline) solid GrayText;
  }

  .smbk-switch__control:disabled + .smbk-switch__track .smbk-switch__thumb {
    border-color: GrayText;
  }

  .smbk-switch__control:disabled:checked + .smbk-switch__track {
    background: GrayText;
  }

  .smbk-switch__control:disabled:checked + .smbk-switch__track .smbk-switch__thumb {
    border-color: Canvas;
    background: Canvas;
  }

  /* The focus ring again, since the rules above set the track's outline. */
  .smbk-switch__control:focus-visible + .smbk-switch__track {
    outline: var(--smbk-focus-ring-width) solid CanvasText;
    outline-offset: var(--smbk-focus-ring-offset);
  }
}
Tokens it reads
Switch tokens
Token and CSSValuePreviewFoundation
space.inline.sm--smbk-space-inline-smcomfortable: 6pxcompact: 4pxchanges with densitySpacing
color.text.default--smbk-color-text-defaultlight: #232527dark: #e7ebf0changes with themeColor
typography.body-sm--smbk-typography-body-sm-font-family--smbk-typography-body-sm-font-size--smbk-typography-body-sm-font-weight--smbk-typography-body-sm-line-height--smbk-typography-body-sm-letter-spacing--smbk-typography-body-sm-text-transformfontFamily: Geist, Geist Fallback, system-ui, sans-seriffontSize: 14pxfontWeight: 400lineHeight: 1.5letterSpacing: 0px

The quick brown fox

Typography
size.target.min--smbk-size-target-min24pxSize
focus.ring.width--smbk-focus-ring-width2pxFocus
color.border.focus--smbk-color-border-focuslight: #cc0d0ddark: #f34336changes with themeColor
focus.ring.offset--smbk-focus-ring-offset2pxFocus
color.text.disabled--smbk-color-text-disabledlight: #7c8692dark: #606a75changes with themeColor
size.target.comfortable--smbk-size-target-comfortable44pxSize
space.stack.md--smbk-space-stack-mdcomfortable: 12pxcompact: 8pxchanges with densitySpacing
size.selection.md--smbk-size-selection-md20pxSize
space.inset.2xs--smbk-space-inset-2xs2pxSpacing
size.selection.lg--smbk-size-selection-lg24pxSize
radius.control.sm--smbk-radius-control-sm4pxRadius
color.surface.track--smbk-color-surface-tracklight: #7c8692dark: #4e555echanges with themeColor
border-width.hairline--smbk-border-width-hairline1pxBorder width
color.border.groove-bottom--smbk-color-border-groove-bottomlight: #ffffffdark: #ffffff0dchanges with themeColor
radius.inset--smbk-radius-inset2pxRadius
color.surface.thumb--smbk-color-surface-thumb#f9fafbColor
elevation.raised--smbk-elevation-raisedlight: 0px 2px 8px 1px #373d431a, 0px 1px 2px 0px #373d431adark: 0px 2px 8px 1px #00000026, 0px 1px 2px 0px #00000026Elevation
color.icon.on-thumb--smbk-color-icon-on-thumb#4e555eColor
size.icon.xs--smbk-size-icon-xs12pxSize
color.surface.brand--smbk-color-surface-brand#cc0d0dColor
color.action.brand.background-hover--smbk-color-action-brand-background-hover#a51d17Color
color.surface.track-subtle--smbk-color-surface-track-subtlelight: #c4cdd8dark: #2d3237changes with themeColor
color.surface.disabled--smbk-color-surface-disabledlight: #e7ebf0dark: #373d43changes with themeColor
color.icon.disabled--smbk-color-icon-disabledlight: #9ba5b1dark: #606a75changes with themeColor
size.selection.sm--smbk-size-selection-sm16pxSize
size.12--smbk-size-1212pxSize
motion.state.duration--smbk-motion-state-duration200msMotion
motion.state.easing--smbk-motion-state-easingcubic-bezier(0.65, 0, 0.35, 1)Motion
space.2--smbk-space-22pxSpacing
space.4--smbk-space-44pxSpacing
Manifest
switch.manifest.json
{
  "name": "switch",
  "block": "smbk-switch",
  "summary": "An on-or-off control that takes effect at once: a filled track with a light thumb that slides to the on side.",
  "adapt": "css",
  "axes": {
    "size": {
      "values": [
        "lg",
        "md",
        "sm"
      ],
      "default": "lg",
      "description": "The track 24, 20 or 16 tall, with its thumb. The small thumb has no room for the tick or the cross."
    }
  },
  "flags": {},
  "parts": [
    "control",
    "track",
    "thumb",
    "on-icon",
    "off-icon",
    "label"
  ],
  "figmaNodeId": "4086:11238"
}