Open any switch, copy the HTML into your form and the CSS into your stylesheet. Each switch is a <label> wrapping a real <input type="checkbox">, so clicking the label toggles it, the space bar toggles it, and the value submits with the form.
To change the color, set --tgl-color on the switch or any ancestor. To change the size, set --tgl-size: the track, knob and icons are in em, so they scale together. Read the state in CSS with :checked, or in JavaScript with input.checked.
Every snippet keeps a visible :focus-visible ring and ships with a prefers-reduced-motion rule, so the knob jumps instead of sliding for people who asked their OS for less motion.
Style a real checkbox as the track, draw the knob with a pseudo-element, and move it with transform when the input is :checked. Every switch above is that pattern with a different look.
Yes, as long as it stays a real checkbox (or has role="switch"), has a label, keeps a visible :focus-visible ring and respects prefers-reduced-motion. The snippets here do all four.
Put the two labels in pseudo-element content or in two spans inside the track, and swap their opacity or position on :checked. The entries tagged "with-text" show several ways.
Yes. :root:has(#theme:checked) can swap your color variables for the whole page. Remembering the choice across visits still needs a line of JavaScript or a cookie.
Use a switch when the change takes effect immediately, like a setting. Use a checkbox when the choice is submitted later with a form.