Переключатель темного режима в веб-приложении

Темный режим (цветовая схема “светлое на темном”) в последние годы стал очень популярен. Предполагается, что он легче переносится глазами и меньше садит батарею. Сегодня такой режим поддерживается всеми основными операционными системами как для настольных, так и для мобильных устройств.

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

Функция prefers-color-scheme

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

body { 
  background: white; color: black;
}

@media (prefers-color-scheme: light) {
  body { 
    background: white; color: black;
  }
}

@media (prefers-color-scheme: dark) {
  body {
    background: black; color: white;
  }
}

В действии этот код можно пронаблюдать в песочнице:

Профессиональный совет

В целях тестирования можно принудительно установить значение как light или dark через инструменты разработчика Chrome. 

Откройте DevTools (F12), нажмите shift+cmd/ctrl+P для открытия командной строки, введите prefers и выберите опцию:

Эти настройки также можно открыть, кликнув по трем вертикальным точкам справа и перейдя в More Tools > Rendering.

Переключатель темного режима

Чтобы добавить для пользователей возможность включать/отключать темный режим, независимо от настроек операционной системы, нам потребуется JavaScript. Начнем с добавления атрибута данных data-color-scheme в корневой элемент. При начальной загрузке страницы это значение будет устанавливаться согласно настройкам системы. 

const getPreferredColorScheme = () => {
  const darkQuery = "(prefers-color-scheme: dark)";
  const darkMQL = window.matchMedia ? window.matchMedia(darkQuery) : {};
  if (darkMQL.media === darkQuery && darkMQL.matches) {
   return "dark";
  }

  return "default";
};

document.documentElement.setAttribute("data-color-scheme", getPreferredColorScheme());

Далее мы добавим набор переменных, которые будут меняться на основе этого атрибута данных.

:root {
  --color-text: #191924;
  --color-background: #fff;
}

:root[data-color-scheme="dark"] {
  --color-text: #fff;
  --color-background: #0d202d;
}

body {
  color: var(--color-text);
  background-color: var(--color-background);
}

Наконец, для переключателя добавьте кнопку в HTML:

<button id="button">Toggle Dark Mode</button>

И обработчик событий click в JavaScript:

document.getElementById("button").onclick = () => {
  const colorScheme = document.documentElement.getAttribute("data-color-scheme");  

 document.documentElement.setAttribute("data-color-scheme", colorScheme === "default" ? "dark" : "default");
};

Живую демоверсию можно посмотреть здесь:

Сохранение выбора пользователя

Вы заметите, что при перезагрузке страницы значение атрибута сбрасывается. Запоминание выбранной пользователем цветовой схемы мы реализуем, сохраняя атрибут данных в локальном хранилище.

При загрузке страницы нужно проверять, есть ли значение, которое можно использовать:

const colorScheme = localStorage.getItem("color-scheme") || getPreferredColorScheme();

document.documentElement.setAttribute("data-color-scheme", colorScheme);

Также нужно сохранять новое значение при использовании переключателя:

document.getElementById("button").onclick = () => {
  const colorScheme = document.documentElement.getAttribute("data-color-scheme");  

const newColorScheme = colorScheme === "default" ? "dark" : "default";  

document.documentElement.setAttribute("data-color-scheme", newColorScheme);  

localStorage.setItem("color-scheme", newColorScheme);
};

Проверить все это можно здесь:

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

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


Перевод статьи Vinicius De Antoni: How to Implement a Dark Mode Switch in Your Web Apps

Предыдущая статьяКак превратить Google Таблицы в базу данных с помощью Python
Следующая статьяКак построить масштабируемый API на Go с помощью Gin