simpletool.io

CSS Switch Generator

iOS-style toggle switches with fully custom styling.

Rendering runs in your browser.
CSS + HTML
<label class="css-switch">
  <input type="checkbox" checked />
  <span class="track"></span>
  <span>Dark mode</span>
</label>

<style>
.css-switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
}
.css-switch input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.css-switch .track {
  position: relative;
  display: inline-block;
  width: 52px;
  height: 28px;
  background: #C1C9D2;
  border-radius: 28px;
  transition: background 180ms cubic-bezier(0.22, 1, 0.36, 1);
}
.css-switch .track::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 22px;
  height: 22px;
  background: #FFFFFF;
  border-radius: 50%;
  box-shadow: 0 1px 2px rgba(0,0,0,0.2), 0 1px 3px rgba(0,0,0,0.1);
  transition: transform 180ms cubic-bezier(0.22, 1, 0.36, 1);
}
.css-switch input:checked + .track {
  background: #635BFF;
}
.css-switch input:checked + .track::after {
  transform: translateX(24px);
}
.css-switch input:focus-visible + .track {
  box-shadow: 0 0 0 3px #635BFF33;
}
</style>

What is a CSS Switch Generator?

A CSS toggle switch (also called a toggle, flip-switch, or iOS-style switch) is a styled boolean control that flips between on and off states. It's the go-to control for settings that apply immediately — dark mode, notifications, feature toggles, "remember me" on login forms — where the user wants a single click and immediate effect rather than a checkbox plus Save button.

Switch vs checkbox. Use a switch when toggling the state has an immediate consequence (the app changes now). Use a checkbox when the state is a selection that's submitted later with a form, or when multiple items are chosen from a set. Mixing them confuses users — a "Save" button next to a switch is a smell.

Implementation pattern. Same as custom checkboxes: hide the native <input type="checkbox"> visually but keep it focusable and form-submittable. Style a sibling .track element with background that changes under :checked, and use a ::after pseudo-element as the circular thumb that slides via translateX(). The native input provides keyboard access (space to toggle) and screen-reader compatibility.

Easing matters. The thumb slide is what makes a switch feel "premium" or cheap. A cubic-bezier(0.22, 1, 0.36, 1) curve (the "Stripe pop") gives a crisp, responsive feel — steep start, decisive stop. Avoidlinear (mechanical) and overly-long durations (> 250ms feels sluggish). Default to 180ms with a Stripe-style ease-out curve.

Accessibility. The native checkbox is still present so screen readers announce it correctly. Add role="switch" and aria-checked on the wrapper if you want screen readers to announce it as a switch rather than a checkbox — the HTML spec added the implicit role="switch" for <input type="checkbox" role="switch"> in 2020, so modern browsers handle this correctly.

Colour choice. The on-state colour should match your brand accent (the default #635BFF here is simpletool.io's). The off-state colour should be neutral grey — reserving your accent for the meaningful state (on). Make sure both states pass contrast requirements against the surrounding background.

How to generate a CSS toggle switch

  1. Pick width and height. 52×28 is the classic iOS size.
  2. Set the on, off, and thumb colours to match your brand.
  3. Copy the HTML + CSS and paste into your component library.

Features

  • Dimensions slider + colour pickers for all three states.
  • Native input preserved for accessibility.
  • Stripe-style easing for a crisp slide feel.
  • Focus-visible ring for keyboard users.
  • Copy-ready HTML + CSS snippet.

Frequently asked questions

When should I use a switch instead of a checkbox?
Use a switch when toggling has an immediate effect — settings, feature toggles, dark mode. Use a checkbox when the state is a selection submitted later with a form. A Save button next to a switch is a design smell.
How do I make the switch accessible?
Our generator keeps the native <input type="checkbox"> in the DOM — it's just visually hidden. Screen readers announce it correctly. For explicit 'switch' role, add role="switch" to the input, which modern browsers honour.
What duration feels best for the slide?
150–200ms with an ease-out curve (cubic-bezier(0.22, 1, 0.36, 1) works great). Faster feels abrupt, slower feels sluggish. Our default is 180ms.
Can I make it keyboard accessible?
Yes — the native input is focusable and space-bar toggles it. We add a focus-visible ring so keyboard users see where focus is.