CSS - Переключатель с использованием JavaScript

В этой статье разберем процесс создания переключателя для сайта с использованием CSS и JavaScript. Кроме этого ещё рассмотрим пример, в котором покажем, как можно отслеживать состояние переключателя и выполнять при его изменении некоторый код.
Что такое переключатель
Переключатель - это элемент интерфейса, предназначенный для выбора одно из двух состояний (включено или выключено).
Данный элемент можно использовать в некоторых случаях в качестве альтернативы checkbox (флажку).
HTML разметка переключателя
HTML код переключателя:
<div class="switch-btn"></div>
Для отображения переключателя во включенном состоянии необходимо дополнительно к switch-btn добавить ещё класс switch-on:
<div class="switch-btn switch-on"></div>
CSS стили для переключателя
Создать дизайн переключателю можно по-разному. В качестве примера рассмотрим 5 вариантов дизайна.
Дизайн переключателя как в Material Design

.switch-btn {
display: inline-block;
width: 62px; /* ширина переключателя */
height: 24px; /* высота переключателя */
border-radius: 12px; /* радиус скругления */
background: #bfbfbf; /* цвет фона */
z-index: 0;
margin: 0;
padding: 0;
border: none;
cursor: pointer;
position: relative;
transition-duration: 300ms; /* анимация */
}
.switch-btn::after {
content: "";
height: 36px; /* высота кнопки */
width: 36px; /* ширина кнопки */
border-radius: 18px; /* радиус кнопки */
background: #fff; /* цвет кнопки */
top: -6px; /* положение кнопки по вертикали относительно основы */
left: -6px; /* положение кнопки по горизонтали относительно основы */
transition-duration: 300ms; /* анимация */
box-shadow: 0 0 10px 0 #999999; /* тень */
position: absolute;
z-index: 1;
}
.switch-on {
background: #fff;
box-shadow: inset 0 0 10px 0 #999999; /* тень */
}
.switch-on::after {
left: 30px;
background: #118c4e;
}
Дизайн переключателя для интерфейсов, не использующих скругления углов

.switch-btn {
display: inline-block;
width: 62px; /* ширина переключателя */
height: 24px; /* высота переключателя */
background: #bfbfbf; /* цвет фона */
z-index: 0;
margin: 0;
padding: 0;
border: none;
cursor: pointer;
position: relative;
transition-duration: 300ms; /* анимация */
}
.switch-btn::after {
content: "";
height: 36px; /* высота кнопки */
width: 36px; /* ширина кнопки */
background: #fff; /* цвет кнопки */
top: -6px; /* положение кнопки по вертикали относительно основы */
left: -12px; /* положение кнопки по горизонтали относительно основы */
transition-duration: 300ms; /* анимация */
box-shadow: 0 0 10px 0 #999999; /* тень */
position: absolute;
z-index: 1;
}
.switch-on {
background: #fff;
box-shadow: inset 0 0 10px 0 #999999; /* тень */
}
.switch-on::after {
left: 36px;
background: #118c4e;}
Дизайн переключателя, в котором кнопка расположена внутри элемента, вдоль которого она перемещается

.switch-btn {
display: inline-block;
width: 72px; /* ширина */
height: 38px; /* высота */
border-radius: 19px; /* радиус скругления */
background: #bfbfbf; /* цвет фона */
z-index: 0;
margin: 0;
padding: 0;
border: none;
cursor: pointer;
position: relative;
transition-duration: 300ms; /* анимация */
}
.switch-btn::after {
content: "";
height: 32px; /* высота кнопки */
width: 32px; /* ширина кнопки */
border-radius: 17px;
background: #fff; /* цвет кнопки */
top: 3px; /* положение кнопки по вертикали относительно основы */
left: 3px; /* положение кнопки по горизонтали относительно основы */
transition-duration: 300ms; /* анимация */
position: absolute;
z-index: 1;
}
.switch-on {
background: #118c4e;
}
.switch-on::after {
left: 37px;
}
Дизайн переключателя с квадратной кнопкой

.switch-btn {
display: inline-block;
width: 72px; /* ширина */
height: 38px; /* высота */
background: #bfbfbf; /* цвет фона */
z-index: 0;
margin: 0;
padding: 0;
border: none;
cursor: pointer;
position: relative;
transition-duration: 300ms; /* анимация */
}
.switch-btn::after {
content: "";
height: 32px; /* высота кнопки */
width: 32px; /* ширина кнопки */
background: #fff; /* цвет кнопки */
top: 3px; /* положение кнопки по вертикали относительно основы */
left: 3px; /* положение кнопки по горизонтали относительно основы */
transition-duration: 300ms; /* анимация */
position: absolute;
z-index: 1;
}
.switch-on {
background: #118c4e;
}
.switch-on::after {
left: 37px;
}
Дизайн переключателя с градиентом

.switch-btn {
display: inline-block;
width: 72px; /* ширина */
height: 38px; /* высота */
background: #bfbfbf; /* цвет фона */
z-index: 0;
margin: 0;
padding: 0;
border: none;
cursor: pointer;
position: relative;
transition-duration: 300ms; /* анимация */
}
.switch-btn::after {
content: "";
height: 32px; /* высота кнопки */
width: 32px; /* ширина кнопки */
background: #fff; /* цвет кнопки */
top: 3px; /* положение кнопки по вертикали относительно основы */
left: 3px; /* положение кнопки по горизонтали относительно основы */
transition-duration: 300ms; /* анимация */
position: absolute;
z-index: 1;
}
.switch-on {
background: #118c4e;
}
.switch-on::after {
left: 37px;
}
JavaScript код для переключателя
Изменение положение переключателя будем выполнять с помощью JavaScript. Для этого достаточно на страницу поместить следующий скрипт:
<script>
$('.switch-btn').click(function(){
$(this).toggleClass('switch-on');
});
</script>
Но, чтобы было более удобно выполнять некоторые действия при изменении состояния переключателя, в js желательно добавить генерацию событий.
<script>
$('.switch-btn').click(function(){
$(this).toggleClass('switch-on');
if ($(this).hasClass('switch-on')) {
$(this).trigger('on.switch');
} else {
$(this).trigger('off.switch');
}
});
</script>
Событие on.switch будет возникать при перемещении ползунка переключателя в положение включено, а off.switch – в выключено.
Пример работы с событиями:
$('.switch-btn').on('on.switch', function(){
console.log('Кнопка переключена в состояние on');
});
$('.switch-btn').on('off.switch', function(){
console.log('Кнопка переключена в состояние off');
});
Пример JavaScript сценария, который будет выполнять действия не только при переключении, но и после загрузки документа.
<script>
$(function(){
$('.switch-btn').click(function (e, changeState) {
if (changeState === undefined) {
$(this).toggleClass('switch-on');
}
if ($(this).hasClass('switch-on')) {
$(this).trigger('on.switch');
} else {
$(this).trigger('off.switch');
}
});
$('.switch-btn').on('on.switch', function(){
console.log('Кнопка переключена в состояние on');
});
$('.switch-btn').on('off.switch', function(){
console.log('Кнопка переключена в состояние off');
});
$('.switch-btn').each(function(){
$(this).triggerHandler('click', false);
});
});
</script>
Финальный пример с двумя переключателями, каждый из которых управляет видимостью определенного блока:
<!-- Два переключателя -->
<div class="switch-btn" data-id="#bl-1" style="margin: 10px;"></div>
<div class="switch-btn switch-on" data-id="#bl-2" style="margin: 10px;"></div>
<!-- Два элемента, первый переключатель управляет видимостью первого элемента, а второй - второго -->
<div id="bl-1" class="bl-hide" style="height: 20px; margin: 10px; background: orange;"></div>
<div id="bl-2" style="height: 20px; margin: 10px; background: lime;"></div>
...
<script>
$(function () {
$('.switch-btn').click(function () {
$(this).toggleClass('switch-on');
if ($(this).hasClass('switch-on')) {
$(this).trigger('on.switch');
} else {
$(this).trigger('off.switch');
}
});
$('.switch-btn').on('on.switch', function () {
$($(this).attr('data-id')).removeClass('bl-hide');
});
$('.switch-btn').on('off.switch', function () {
$($(this).attr('data-id')).addClass('bl-hide');
});
});
</script>
Комментарии: 17
Здравствуйте. Мой вопрос немного не по статье, за что прошу прощения (в том плане что не этот код используется), а js я не знаю (не дошел до него). Я нашел себе этот переключатель тем (https://codepen.io/pwadev/pen/xxqogKr), встроил к себе в верстку, переключение тем работает на текущей странице нормально (при обновлении тема не сбрасывается), но стоит перейти на другую страницу по ссылке - то все, значение стоит по умолчанию (темная). И да, для понимания я верстаю локально , т.е. страницы (7шт на текущий момент, 7 файлов .html и 1 файл .css) открываю в браузере по ссылке file:///... , без подключения локальных серверов или подключения сайта к инету (домен и прочее). В каждую страницу добавлен переключатель. Как я понимаю из своей ситуации (моя мысля), я скорее всего по сути загружаю как бы отдельный сайт (то бишь страницу), поэтому для каждой страницы и стоит по умолчанию темная, т.е. страницы мои как бы не связанны вместе, хоть и переключатель везде стоит на них; ну или код не корректен или я дурак.
Помогите пожалуйста! Или как в вашем примере в статье сделать переключение тем (светлая и темная)?а не, ответ нашел: Да, если вы разместите свой сайт на веб-сервере (с локальным сервером или на реальном хостинге с доменом), то проблема сохранения состояния темы в localStorage решится. Это происходит потому, что localStorage привязан к домену, и он будет общим для всех страниц вашего сайта на этом домене. Таким образом, состояние темы будет сохраняться между страницами даже после перезагрузки.
При использовании локальных файлов (как вы делали с "file:///..."), каждая страница рассматривается браузером как отдельный домен, поэтому localStorage не общий между ними.
Итак, чтобы сохранить состояние темы между страницами, вам потребуется разместить свой сайт на веб-сервере с доменом или использовать локальный сервер (например, Open Server), который симулирует работу сервера и позволяет вам работать с сайтом так, как будто он находится в интернете.
Добрый день!
Если пользуетесь Visual Studio Code или каким-то другим редактором, то в большинстве это можно решить намного проще (через расширение). Например, можно установить Live Server.
Обычно не открываю файлы так как описали, всегда использую какой-то сервер. Решил проверить это утверждение. Добавил в один файл установку некоторого значения в LocalStorage:
localStorage.setItem('a', 'a')
. Открыл её отдельно с помощью Chrome. Потом другую страницу, значение есть. То есть Origin у них один, этоfile://
. Как в других браузерах не проверял. Поэтому в Chrome должно это работать и так, без сервера.Если нужен пример с переключением тем, то могу сделать.
Благодарю за отклик на мою проблему. Свой вопрос я решил уже, путем закидывания своих страниц на GitHub Pages (ну и там все корректно работает; вообщем сам дурак + еще кипишь развел... эх). Проблема действительно была в не связанности страниц между собой под одним доменом (локальным или реальным). За подсказку насчет расширения - спасибо, в эту сторону я и не думал даже, а юзаю и вправду VScode.
Вопрос такой, можете сделать из этого кода (https://codepen.io/pwadev/pen/xxqogKr) переключатель для трех тем?) к примеру темная, светлая и пергамент.
В примере работа переключателя основана на чекбоксе
<input type="checkbox">
. Чекбокс имеет 2 состояния, а тут нужно три. Для этого случая это нужно организовать как-то по-другому. Например, сделать это просто на JavaScript.Вот код:
Чтобы он переключатель между такими таблицами + выбор кнопки. Благодарю.
Например:
Пример в песочнице доступен по этой ссылке.