Warning: include(/volume1/web/cyberhost.biz/wp-content/plugins/jaster_cahce/cache/top-cache.php): failed to open stream: No such file or directory in /volume1/web/cyberhost.biz/index.php on line 9 Call Stack: 0.0001 356272 1. {main}() /volume1/web/cyberhost.biz/index.php:0 Warning: include(): Failed opening '/volume1/web/cyberhost.biz/wp-content/plugins/jaster_cahce/cache/top-cache.php' for inclusion (include_path='.:/usr/share/pear') in /volume1/web/cyberhost.biz/index.php on line 9 Call Stack: 0.0001 356272 1. {main}() /volume1/web/cyberhost.biz/index.php:0 Трёхпозиционный checkbox (aka tristate) без скриптов и смс | Хостинг за 90 р. от cyberhost.biz — платный хостинг
+7 993 930-19-90 suport@cyberhost.biz

Понадобилось мне недавно реализовать трёхпозиционный переключатель. Ну это такой, у которого вместо двух состояний «включено/выключено», есть ещё промежуточное состояние. Это часто используется, например, в чекбоксе «выбрать всё», для того чтобы показать, что выбраны не все элементы, а только часть. В общем, захотелось такое реализовать, да чтобы без скриптов.

Пример элемента на gmail:

Беглое гугление не выдало мне готового решения без JavaScript. Точнее, я нашёл парочку, но они предлагали для изменения состояния кликать в конкретное место на переключателе, что совсем неудобно. Хотя в основном предлагают использовать либо свойство DOM indeterminate у чекбокса, либо написание компонента на скриптах, начиная с jQuery, заканчивая Angular. Но мне как-то не хотелось ради такой простой задачи подключать JS вообще.

Ещё из пожеланий — мне хотелось иметь рабочий кликабельный label, а так как состояния три, то чтобы этот label показывал текущее состояние.

Как я это реализовал? В основе — обычные радио-инпуты спозиционированые абсолютно в верхний левый угол. А вся магия заключается в изменении z-index в зависимости от текущего выбранного элемента. Кусочек из CSS:
.tristate > input[type="radio"]:checked + input[type="radio"] {
z-index: 10;
}

Иконка и текущий лейбл стилизуется подобными правилами:
.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 {
/* … */
}

Осталось всё немного застилизовать, и получаем два симпатичных UI-компонента, как на картинке к посту:

Демо на CodePen

Работоспособность проверял в FF, Chrome, IE9+.

Warning: include(/volume1/web/cyberhost.biz/wp-content/plugins/jaster_cahce/cache/bottom-cache.php): failed to open stream: No such file or directory in /volume1/web/cyberhost.biz/index.php on line 13 Call Stack: 0.0001 356272 1. {main}() /volume1/web/cyberhost.biz/index.php:0 Warning: include(): Failed opening '/volume1/web/cyberhost.biz/wp-content/plugins/jaster_cahce/cache/bottom-cache.php' for inclusion (include_path='.:/usr/share/pear') in /volume1/web/cyberhost.biz/index.php on line 13 Call Stack: 0.0001 356272 1. {main}() /volume1/web/cyberhost.biz/index.php:0