Как добавить темную тему на свой сайт с помощью CSS и JavaScript

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

У нас будет 3 разных варианта темы - Auto (Авто), Light (Светлая) и Dark (Темная). Темы Light и Dark говорят сами за себя, но тема Auto будет использовать настройку темы операционной системы, чтобы решить, будет ли сайт светлым или темным.

Я не буду показывать вам, как создать этот конкретный макет или включить его в наш контент, вот пример того, что мы могли бы создать:

Светлая и темная тема

Добавление HTML

Начнем с HTML, мы можем представить атрибуте value в теге option как об идентификаторе для каждой темы:

<select id="theme">
    <option value="auto">Auto</option>
    <option value="light">Light</option>
    <option value="dark">Dark</option>
</select>

Добавление CSS

Давайте теперь добавим немного CSS к тегу body, здесь вы указываете свои цвета для Light темы с помощью CSS-переменных:

body {
    --background-color: #ffffff;
    --text-color: #000000;
}

Затем вы можете использовать свои CSS-переменные во всей таблице стилей - это ключ к тому, как наше решение будет работать. Например, вы можете сделать:

.main-content {
    background: var(--background-color);
    color: var(--text-color);
}

button {
    color: var(--text-color);
}

Мы собираемся реализовать темную тему, просто заменив значения объявленных выше переменных в тех случаях, когда мы собираемся использовать темную тему. Добавим этот CSS код:

:root {
    --dark-background-color: #111111;
    --dark-text-color: #eeeeee;
}

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

Теперь, если вы добавите класс theme-dark к своему элементу, вы увидите, что темная тема работает. Вскоре мы будем использовать JavaScript для переключения этого значения, но давайте сейчас реализуем нашу опцию Auto:

@media (prefers-color-scheme: dark) {
    body.theme-auto {
        --background-color: var(--dark-background-color);
        --text-color: var(--dark-text-color);
    }
}

Вышеупомянутый CSS использует Media Queries, который проверяет, предпочитает ли операционная система темную тему, и если да, мы хотим применить вложенный набор правил для body.theme-auto.

По сути, мы говорим: «Предпочитает ли операционная система темный режим и есть ли у нее класс theme-auto? Если да, давайте использовать темный режим».

Попробуйте, изменив цвет темы своей ОС, или, что еще лучше, просмотрите веб-сайт на своем телефоне с включенным темным режимом.

Добавление JavaScript

Теперь, когда наш CSS работает, мы можем перейти к работе раскрывающегося списка выбора темы. Добавим следующий JavaScript:

function applyTheme(theme) {
    document.body.classList.remove("theme-auto", "theme-light", "theme-dark");
    document.body.classList.add(`theme-${theme}`);
}

document.addEventListener("DOMContentLoaded", () => {
   document.querySelector("#theme").addEventListener("change", function() {
        applyTheme(this.value);
   });
});

Здесь мы ждем, пока DOM будет готов, чтобы мы могли начать его использовать, и как только он будет готов, мы ожидаем, когда пользователь выбирает вариант в раскрывающемся списке выбора темы. После того, как пользователь изменит тему, мы удалим все существующие классы тем из <body> (если есть), а затем просто добавим выбранную тему с помощью this.value.

Запоминание темы

Мы могли бы пойти дальше и дать браузеру возможность запоминать тему, выбранную при обновлении страницы. Для этого мы можем использовать Local Storage

Давайте добавим следующий JavaScript код, чтобы в итоге получилось следующее:

document.addEventListener("DOMContentLoaded", () => {
    const savedTheme = localStorage.getItem("theme") || "auto";

    applyTheme(savedTheme);

    for (const optionElement of document.querySelectorAll("#theme option")) {
        optionElement.selected = savedTheme === optionElement.value;
    }

    document.querySelector("#theme").addEventListener("change", function () {
        localStorage.setItem("theme", this.value);
        applyTheme(this.value);
    });
});

Теперь, выбрав тему, мы сохраняем ее в локальном хранилище, используя localStorage.setItem("theme", this.value). После этого при загрузке страницы мы загружаем ранее сохраненную тему в константу savedTheme со значением по умолчанию aut. Если у нас есть значение в хранилище, то мы просто применяем сохраненную тему.

Затем мы перебираем каждый из наших элементов и проверяем, совпадает ли значение с нашей сохраненной темой, и если да, выбираем этот вариант как selected.

Чтобы проверить, работает ли он, обновите страницу, выберите тему, обновите еще раз, и ваша тема должна остаться!