Переключатель в стиле iOS на CSS
Опубликовал Александр Шабуневич — 19 Август 2012, 22:43
Понадобилось мне сделать виджет для переключения (тумблер) в стиле iOS. При этом хотелось, чтобы он работал на чистом CSS (без JavaScript) и во всех современных браузерах. Еще хотелось, чтобы разметка была минимальной — только самое необходимое. Семантически же элемент был задуман как «переключалка» между двумя разными состояниями (а не просто вкл/выкл), что наводило на мысль об использовании двух радио-кнопок. Выглядеть это должно примерно так:
Чтобы не изобретать свой велосипед, я полез искать готовые решения в интернете. Нашел много хороших вариантов, но подходящего мне на 100% не нашлось. Большинство или требовали скриптов, или же были организованы с помощью одного чекбокса, а не радио-кнопок. Кроме того, многие варианты работают лишь в webkit-браузерах, что меня не устраивало.
В общем, пришлось делать свой вариант и выкладывать его для общего пользования. Начал я с такой разметки:
<div class="switch">
<input type="radio" name="radio" id="radio-1" checked> <label for="radio-1">Option 1</label>
<input type="radio" name="radio" id="radio-2"> <label for="radio-2">Option 2</label>
</div>
Элементы label
специально написаны после инпутов, а не оборачивают их, чтобы впоследствии я смог к ним обратиться при помощи селектора input:checked + label
.
Так как засорять код лишними обертками и элементами мне не хотелось, для оформления я решил использовать псевдоэлементы :before
и :after
. Теоретически, можно было попробовать разукрасить сами радио-кнопки, но, к сожалению, свойство appearance работает пока лишь в Firefox и Safari/Chrome, а мне хотелось захватить еще как минимум Оперу, а может и IE9+.
Мне понадобились оба псевдоэлемента: один для обозначения фона, второй — для самого бегунка. Вообще, :before
и :after
штуки очень удобные для чистой верстки, но даже современные браузеры поддерживают их с определёнными ограничениями. Например, свойство transition
(которое я использовал для анимации переключения тумблера) должно работать не только для элементов, но и для псевдоэлементов. Однако работает оно лишь в Firefox.
Первый вариант анимации как раз и работал только в Firefox. Но потом я решил, что хорошо было бы добавить анимацию переключения и в другие браузеры, и переделал код. Теперь с анимацией изменялись границы самих элементов label
, а это, в свою очередь, анимировало и псевдоэлементы.
Потом появилась еще одна идея: заставить переключатель срабатывать по клику на самом бегунке (а не только при клике по надписям). Для этого пришлось расширить свойство padding
у неактивного label
. Зато теперь вся конструкция работает на чистом CSS.
Единственный минус, который я пока не смог обойти: в Сафари и Хроме правая подпись немного дергается при переключении. Некритично, но неприятно. Можно, конечно, отключить анимацию для этих браузеров — функциональность при этом не пострадает. Но может быть есть какой-то более элегантный способ это обойти. Если вы его знаете, буду рад услышать предложения.
Почему LESS? Потому что у него есть замечательный Simpless!
Да, после всего я еще сделал LESS-версию данного переключателя, так как для моего проекта это очень удобно. В ней можно настраивать цвет фона, размер самого переключателя и отступов от надписей.
Вы можете посмотреть демо-версию и скачать код в репозитории.
Комментарии
1. В слове репозиторий нет буквы «а».
2. Не вижу переключателя: http://i46.tinypic.com/2d8kvgy.png
В целом здорово, но когда на iOS что-то выключается, то меняется цвет подложки с синего на серый. И наоборот. Я уж не говорю о обозначении “I”/“O” там же.
miripiruni, спасибо, это другое слово просто =)
В FF и Хроме действительно почему-то не подгрузился CSS — вчера пример только в Опере проверил. Сейчас всё должно быть нормально.
GreLI, цвет подложки и I/O — это скорее признак чекбокса, т.е. вкл/выкл. Таких примеров в сети много. Мне нужно было именно переключение между двумя состояниями, а в этом случае цвет подложки ни к чему.