Перейти к навигации · Перейти к содержимому

Переключатель в стиле iOS на CSS

Теги

Понадобилось мне сделать виджет для переключения (тумблер) в стиле 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 — это скорее признак чекбокса, т.е. вкл/выкл. Таких примеров в сети много. Мне нужно было именно переключение между двумя состояниями, а в этом случае цвет подложки ни к чему.