
It took me recently to implement a three-way switch. Well, this is one that, instead of two states "on / off", there is also an intermediate state. This is often used, for example, in the “select all” checkbox in order to show that not all elements are selected, but only a part. In general, I wanted to implement this, so that without scripts.
An example of an item on gmail:

Quick googling did not give me a ready-made solution without JavaScript. More precisely, I found a couple, but they suggested clicking on a particular place on the switch to change the state, which is quite inconvenient. Although basically they propose to use either the DOM
indeterminate
property of the checkbox or writing a component on scripts, starting with jQuery and ending with Angular. But I somehow did not want for the sake of such a simple task to connect JS at all.
')
Also from wishes - I wanted to have a working clickable
label
, and since there are three states, then this
label
show the current state.
How did I implement it? At the heart of it is the usual radio inlets which are positioned absolutely in the upper left corner. And all the magic is to change the
z-index
depending on the currently selected item. CSS Slice:
.tristate > input[type="radio"]:checked + input[type="radio"] { z-index: 10; }
The icon and the current label are styled with similar rules:
.tristate > input[type="radio"]:checked + i + label, .tristate > input[type="radio"]:checked + i + label + label { display: none; } .tristate-checkbox > input[type="radio"]:checked + input[type="radio"] + i { }
Everything remains to be slightly zastilizovat, and we get two cute UI-components, as in the picture for the post:
CodePen demoOperability tested in FF, Chrome, IE9 +.
UPDATE: Added a version with a "twist":
