Как написать переключатель темы на базе файлов cookie с помощью CSS и ванильного JavaScript

HTML-код

Для демонстрации темной темы понадобится простой HTML-файл. В раздел head включены CSS-файл styles.css и два файла JavaScript: darkmode.js и project.js.

Мета-параметры  —  кодировка, вид экрана и заголовок  —  упоминаются только для заполнения минимального раздела заголовка.

Кнопка переключения на темную тему  —  darkmode  —  расположена внутри элемента <header> на тринадцатой строчке.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
<title>Darkmode-Switch</title>
<link rel="stylesheet" href="css/styles.css">
<script src="js/darkmode.js" defer></script>
<script src="js/project.js" defer></script>
</head>
<body>
<header>
<button class="darkmode" title="darkmode switch" aria-hidden="true"></button>
</header>
<main></main>
<footer></footer>
</body>
</html>

CSS-код

В таблице стилей определяется тело (body) в светлом и темном режиме. Также устанавливается дизайн для переключателя темы в статусе lightmode и darkmode (имя класса, ответственного за это  —  active).

Данный CSS максимально прост.

*{
box-sizing:border-box;
}

body{
font-family:sans-serif;
background-color:#fff;
color:#000;
}
body.darkmode{
background-color:#000;
color:#fff;
}

header .darkmode{
position:absolute;
right:2rem;
top:2rem;
width:4rem;
height:1.5rem;
border-radius:500px;
border:2px solid #888;
background-color:transparent;
cursor:pointer;
appearance:none;
}
header .darkmode::before{
content:'';
position:absolute;
left:4px;
top:50%;
width:1rem;
height:1rem;
background-color:#888;
border-radius:50%;
transform:translateY(-50%);
}
header .darkmode.active::before{
left:auto;
right:4px;
}

Файл project.js

Этот файл используется для инициализации темной темы с помощью функции darkmode_init()  —  которая будет описана позже  —  в событии DOMContentLoaded.

document.addEventListener('DOMContentLoaded',function()
{
darkmode_init();
});

Файл darkmode.js

В этом примере от начала и до конца описана функция для переноса поведения темной темы. Вот полный сценарий:

function darkmode_init()
{
let darkmodeSwitch = document.querySelector('header .darkmode');

let darkmodeCookie = {
set:function(key,value,time,path,secure=false)
{
let expires = new Date();
expires.setTime(expires.getTime() + time);
var path = (typeof path !== 'undefined') ? pathValue = 'path=' + path + ';' : '';
var secure = (secure) ? ';secure' : '';

document.cookie = key + '=' + value + ';' + path + 'expires=' + expires.toUTCString() + secure;
},
get:function()
{
let keyValue = document.cookie.match('(^|;) ?darkmode=([^;]*)(;|$)');
return keyValue ? keyValue[2] : null;
},
remove:function()
{
document.cookie = 'darkmode=; Max-Age=0; path=/';
}
};


if(darkmodeCookie.get() == 'true')
{
darkmodeSwitch.classList.add('active');
document.body.classList.add('darkmode');
}


darkmodeSwitch.addEventListener('click', (event) => {
event.preventDefault();
event.target.classList.toggle('active');
document.body.classList.toggle('darkmode');

if(document.body.classList.contains('darkmode'))
{
darkmodeCookie.set('darkmode','true',2628000000,'/',false);
}
else
{
darkmodeCookie.remove();
}
});
}

Теперь рассмотрим процесс в четыре простых шага.

Шаг 1. Ссылка на кнопку

Сначала перехватываем переключатель из DOM.

let darkmodeSwitch = document.querySelector('header .darkmode');

Объект darkmodeCookie содержит три метода.

  • set, чтобы задать файл cookie для темной темы.
  • get, чтобы прочитать файл cookie, если он существует.
  • remove, чтобы удалить файл cookie.
let darkmodeCookie = {
set:function(key,value,time,path,secure=false)
{
let expires = new Date();
expires.setTime(expires.getTime() + time);
var path = (typeof path !== 'undefined') ? pathValue = 'path=' + path + ';' : '';
var secure = (secure) ? ';secure' : '';

document.cookie = key + '=' + value + ';' + path + 'expires=' + expires.toUTCString() + secure;
},
get:function()
{
let keyValue = document.cookie.match('(^|;) ?darkmode=([^;]*)(;|$)');
return keyValue ? keyValue[2] : null;
},
remove:function()
{
document.cookie = 'darkmode=; Max-Age=0; path=/';
}
};

Шаг 3. Обработка классов CSS

Метод get объекта darkmodeCookie позволяет проверить, существует ли файл cookie для темной темы. Если да, то добавляем класс active к переключателю и класс darkmode в тело body.

if(darkmodeCookie.get() == 'true')
{
darkmodeSwitch.classList.add('active');
document.body.classList.add('darkmode');
}

Шаг 4. Управление переключателем

Эта часть скрипта добавляет прослушиватель событий к переключателю, чтобы была возможность изменять классы как в самом переключателе, так и в теле страницы.

В шестой строке кода проверяем, есть ли у body класс darkmode после переключения, которое происходит на четвертой строке. Если это так, устанавливаем файл cookie darkmode, срок действия которого в этом примере истекает через один месяц (2 628 000 000 миллисекунд).

Последнему параметру darmodeCookie.set() в восьмой строке должно быть присвоено значение true, если страница зашифрована по протоколу SSL. Для локального тестирования просто установите туда false. Второй параметр  —  это значение, здесь используется просто true в качестве строки.

Если файл cookie необходимо удалить, поскольку body не содержит класса darkmode, применяется darkmodeCookie.remove().

darkmodeSwitch.addEventListener('click', (event) => {
event.preventDefault();
event.target.classList.toggle('active');
document.body.classList.toggle('darkmode');

if(document.body.classList.contains('darkmode'))
{
darkmodeCookie.set('darkmode','true',2628000000,'/',false);
}
else
{
darkmodeCookie.remove();
}
});

Заключение

С помощью этих простых шагов вы можете сделать сайт более удобным для пользователя. Для большей гибкости и контроля также можно устанавливать класс darkmode в body с помощью PHP, а не JavaScript.

Читайте также:

Читайте нас в TelegramVK и Яндекс.Дзен


Перевод статьи Stephan Romhart: Code a cookie-based darkmode switch in CSS and vanilla JavaScript

Предыдущая статьяОт 0 до 300 SQL-запросов в месяц: 3 практических совета
Следующая статьяКак быстро и легко создавать прототипы датасайенс-проектов