Можно ли использовать JavaScript для переключения между светлым и темным режимами на странице?

я могу использовать

@media (prefers-color-scheme: dark)

or

window.matchMedia('(prefers-color-scheme: dark)').matches

чтобы определить, является ли это темным режимом ОС.

Однако есть ли способ самостоятельно изменить статус с помощью JavaScript? Чтобы я мог создать кнопку, позволяющую пользователям переключаться между темным и светлым, если они не хотят сохранять настройки ОС.


person AGamePlayer    schedule 13.01.2021    source источник
comment
Вы не можете изменить значение prefers-color-scheme, но вы можете использовать классы и другие методы для обеспечения светлого и темного режимов для вашего веб-сайта.   -  person Heretic Monkey    schedule 13.01.2021
comment
Нет, вы не можете изменить такие настройки с помощью скрипта из контекста веб-страницы. Для этого вы можете использовать дополнительный класс, который переопределяет стили, определенные этими медиа-запросами, но в зависимости от того, сколько форматирования вам нужно изменить, вы можете в конечном итоге удвоить большой объем кода. (Вы не можете использовать одно правило для обоих, но вам придется повторить все стили, один раз в @media() { … } и один раз в .myspecialclass { … })   -  person CBroe    schedule 13.01.2021
comment
(Если только нельзя использовать переменные CSS внутри спецификатора медиа-запроса, но я не думаю, что это на самом деле возможно?)   -  person CBroe    schedule 13.01.2021
comment
Будет drafts.csswg.org/mediaqueries-5/#script-custom -mq, который позволил бы установить блок стиля для двух медиа-запросов, но он нигде не реализован, и действительно неясно, будет ли он когда-либо.   -  person Kaiido    schedule 14.01.2021


Ответы (1)


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

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

Что я делаю, так это сохраняю настройки пользователя в localStorage и следую сохраненным предпочтениям, когда они в следующий раз вернутся (даже если они изменили свои системные настройки).

Для отображения темного режима я добавляю класс темного режима в documentElement (тег html). В моем CSS есть второй набор наборов правил CSS:

<style>
    body {
        background-color: #FFFFFF;
        font-family: 'Open Sans', sans-serif;
        color: #212121;
        font-weight: 400;
        line-height: 1.125em;
        height: 100%;
    }

    .dark-mode body {
        background-color: #121212;
        color:  #ffffff;
    }
</style>

Другой вариант переключения цветов - применить к тегу атрибут data-color-mode = dark и использовать переменные CSS:

:root {
  --background-color: #f0f0f0;
  --paragraph-color: #333;
}

[data-color-mode="dark"] {
  --background-color: #333;
  --paragraph-color: #ccc;
}

Переменные CSS не будут работать с Internet Explorer, поэтому он вернется к стандартным цветам IE.

Поскольку мне все еще нужна поддержка IE9 и выше, я не использую параметр переменной CSS и, поскольку я использую отложенную загрузку на основе crossctionObserver, я не даю пользователям IE возможность переключать тему - они автоматически получают свет тема.

Чтобы это работало, у меня в голове есть следующий код:

// IE doesn't get the dark mode option – I use IntersectionObserver as a proxy for IE
if ("IntersectionObserver" in window)  {
    window.dark = JSON.parse(window.localStorage.getItem("theme_mode"));
    if (window.dark === null) { // First time - use prefers color to set the theme
        if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches) {
            window.dark = true;
            document.documentElement.className = document.documentElement.classList.add("dark-mode");
        } else {
            window.dark = false;
        }
        localStorage.setItem("theme_mode", JSON.stringify(window.dark));
    } else if (window.dark === true) { // Returning user - prefers dark
        document.documentElement.classList.add("dark-mode");
    } // Returning user - prefers light - window.dark is false
} else { // Browser is IE - hide dark mode stuff
    document.documentElement.classList.add(" ie");
}

IE9 не поддерживает classList, но при желании я загружаю полифилл, если посетитель использует IE9.

Чтобы настроить функцию переключения, у меня есть следующий код внизу моей страницы:

// set the selector switch to the right setting
var modeToggle = document.getElementById("light-dark-toggle");
if (window.dark) {
    modeToggle.checked = true;
} else {
    modeToggle.checked = false;
}

    
modeToggle.addEventListener('change', function() {
    window.dark = modeToggle.checked;
    if (window.dark) {
        document.documentElement.classList.add("dark-mode");
    } else {
        document.documentElement.classList.remove("dark-mode");
    }
    localStorage.setItem("theme_mode", JSON.stringify(window.dark));
    lazyLoad();
});

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

person Rich DeBourke    schedule 14.01.2021