UX Pickle

Designing effective toggle buttons

Reading Time - 6 minA toggle switch is for one binary setting that takes effect the instant it is flipped — Wi-Fi on or off, notifications on or off. If the change needs a Save button, if the two states are named alternatives like List and Map, or if the user is picking several things from a list, a switch is the wrong control. Use a checkbox, a radio group or a segmented button instead.

Reading Time - 6 min

A toggle switch is for one binary setting that takes effect the instant it is flipped — Wi‑Fi on or off, notifications on or off. If the change needs a Save button, if the two states are named alternatives like List and Map, or if the user is picking several things from a list, a switch is the wrong control. Use a checkbox, a radio group or a segmented button instead.

Key points

  • A switch controls one binary setting and applies it immediately, with no Save button.
  • Label what the switch does when it is on, and keep that label outside the control.
  • Never signal state by colour alone; add an icon or a text label.
  • Give every switch a default state and a target of at least 24 × 24 CSS pixels.
  • For two named alternatives, use a segmented control.

A switch is one setting, not a choice between two things

This is the distinction designers get wrong most often. Material 3 puts it plainly: switches control binary options, not opposing ones. A binary option is one thing that is either on or off — aeroplane mode, two‑factor authentication. Opposing options are a set where exactly one member can be active, like a list view versus a map view; for those, Material 3 sends you to a connected button group.

The test is whether you can write the label as a single thing that is present or absent. “Show archived projects” passes. “List / Map” fails, because neither one is the absence of the other.

Apple draws a second line. On iOS and iPadOS the Human Interface Guidelines say to use the switch style only in a list row, where the row supplies the context. Outside a list Apple wants a button that behaves like a toggle — the Phone app’s filter button, which simply gains a blue background when active.

The change has to happen immediately

Material 3 is unambiguous here: the effects of a switch should start immediately, without needing to save. A switch sitting in a long form next to text fields and a Submit button is a bug, not a style choice — the user has no way to know whether flipping it did anything. In that context a checkbox is the honest control, because a checkbox visibly means “this will be applied when you submit”.

If the setting needs a round trip to a server, keep the switch but show the pending state inline: move the handle straight away, put a small spinner where the handle icon goes, and roll the switch back with an error if the request fails. What you must not do is leave the handle in its old position while the call runs, because people will tap it again.

Give every switch a default state

A switch is never empty. It is on or off from the moment the screen renders, so you are always deciding on the user’s behalf. Pick the default that is safest and least surprising, not the one best for you: off by default for anything that shares data, on by default for anything that protects the user.

If you genuinely need a third state — unanswered — then you do not want a switch at all. A required yes/no question wants two radio buttons, because an untouched radio group is visibly unanswered and an untouched switch is not.

Write the label for the on state

Material 3’s rule is that a label should describe what the control does when the switch is on. So “Show average price” is right and “Do you want to see the average price?” is wrong — a question implies a Yes/No answer, which is a radio group, not a switch. Keep it to a couple of words where you can, use a noun or a verb phrase, and put it on the leading edge with the switch on the trailing edge so a column of settings lines up.

Material 3 also warns against putting the label text inside the control: the type ends up too small to be accessible. Use an icon in the handle if you need something in there.

Two shadcn/ui settings cards, Share across devices switched off and Enable notifications switched on, each with a bold label and a sentence of helper text
shadcn/ui’s switch component, one of the most widely used React UI kits in 2026. Each switch carries a short label plus a sentence of helper text, and the label describes the setting rather than asking a question.

The same discipline that keeps button labels clear applies here. If you are weighing up two candidate words for a control, our guide to choosing between ‘exit’, ‘quit’ and ‘close’ works through the same problem for destructive and dismissive actions.

Do not let colour carry the state

Apple’s guidance is explicit: avoid relying solely on different colours to communicate state, because not everyone can perceive the difference. A green track and a grey track are the same track to a large number of people, and they are indistinguishable in a screenshot printed in greyscale.

Two iOS list rows from Apple's Human Interface Guidelines: one switch off in grey, one on in the standard green, beside the same pair using a custom purple accent colour
Apple’s Human Interface Guidelines for Toggles, showing the standard green switch beside a custom accent colour. Apple asks you to change the default only if you need to, and to check the tinted state contrasts with the untinted one.

Both major platforms now ship a redundant cue rather than relying on the track colour. Material 3 Expressive, which reached Pixel devices with the Android 16 QPR1 release in September 2025 and carried through to Android 17, puts a checkmark in the handle when the switch is on and an × when it is off, and grows the handle in the on state. Material’s own advice is to pick icons that are unambiguously binary — a checkmark and an × — rather than something like a moon or a pencil.

Material Design 3 guidance panel: a Do example showing switches with an X icon when off and a checkmark when on, and a Don't example showing a moon and a pencil icon
Material 3’s do‑and‑don’t for handle icons. The icon has to say “on” or “off” on its own; a moon says “night”, which is a different question.

iOS has offered the same redundancy as a user setting for years: Accessibility › Display & Text Size › On/Off Labels adds an I to switches that are on and an O to switches that are off, across system settings and any app using the standard control. That is a good reason to use the platform switch rather than rolling your own — a custom control silently opts your users out of it.

If you are picking a custom on‑state colour, check it properly rather than eyeballing it. Our colour code converter will give you the HEX, RGB, HSL and OKLCH values for the colour you have chosen, which is what you need before you can reason about whether the on and off states really differ by more than hue.

Make it big enough to hit

WCAG 2.2 added Success Criterion 2.5.8 Target Size (Minimum) at Level AA: pointer targets must be at least 24 × 24 CSS pixels, unless one of the listed exceptions applies — spacing, an equivalent control elsewhere, inline targets, user‑agent‑controlled sizing, or an essential presentation.

A drawn switch is often smaller than that. The usual fix is to make the whole settings row the target, so label and switch are one hit area, and to give rows enough vertical padding that neighbouring switches are not 24 pixels apart. In a stacked settings list the cost of a mis‑tap is flipping the wrong setting without noticing.

Mark it up as a switch

On the web there are two defensible implementations. Either use a native <input type="checkbox"> with a visually styled label, which gives you keyboard support and form semantics for free, or use a <button> with role="switch" and aria-checked, which is what shadcn/ui, Radix and most current component libraries do. Either way the control needs a programmatic name — a real <label for> or an aria-label — because a switch with no accessible name is announced as nothing more than “switch, off”.

What you should not do is put the current state into the accessible name, as in “Notifications on”. The state is already announced from aria-checked, so you end up with “Notifications on, switch, on”. Name the setting; let the role carry the state.

Do and don’t

  • Do apply the change the moment the switch moves.
  • Do label the setting, and write the label for the on state.
  • Do add an icon or text label so state does not depend on colour.
  • Do make the whole row the target, at least 24 × 24 CSS pixels.
  • Don’t put a switch in a form that has a Save button — use a checkbox.
  • Don’t use a switch to pick between two named views — use a segmented control.
  • Don’t put text inside the switch track.
  • Don’t repeat the state in the accessible name.

Check the ones you have already shipped

Toggle problems arrive gradually. One screen uses a switch with a Save button, another a checkbox for the same kind of setting, a third a switch whose label reads as a question. None is obviously broken alone; together they make a product feel careless. Running a free audit of your site catches the mechanical half — unlabelled controls, undersized targets, failing contrast — and leaves a shorter list to review by eye.

4 Comments

  1. A quite excellent article. We feel thankful for your blog article. I have found a good lot of strategies after visiting your article.

  2. I like the way you write and share your specialized niche! Some what interesting and several! Keep it coming!

  3. A quite excellent writing. We have always been thankful for your site post. I have found the lot of strategies soon after visiting your blog post.

Comments are closed.