简体   繁体   中英

Is it possible to use JavaScript to switch between light mode and darkmode on a page?

I can use

@media (prefers-color-scheme: dark)

or

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

to detect whether it's a dark mode the OS.

However, is there any way that I can modify the status on my own with JavaScript? So that I can create a button to let the users switch between dark and light if they don't want to keep the OS's settings.

Perhaps the easiest way to support dark mode is to define all of your color settings for text, backgrounds, borders, shadows, etc. for your light theme, and then use a media query to override the colors, but as you noted, that doesn't give your visitor the option to switch.

To give your visitors a choice, you can add a small, unobtrusive switch to your page (some sites, such as GitHub display a switch on their desktop version, but to switch on a mobile device, the user has to open the Settings function).

What I do is I save the user's preference in localStorage and I follow the stored preference the next time they come back (even if they've changed their system setting).

For displaying dark mode, I add a dark-mode class to the documentElement (the html tag). In my CSS, I have a second set of CSS rule-sets:

<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>

Another option for switching the colors is to apply a data-color-mode="dark" attribute on the tag and using CSS variables:

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

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

The CSS variables won't work with Internet Explorer, so it will revert to IE's standard colors.

As I still need to support IE9 and up, I don't use the CSS variable option and, because I use an intersectionObserver based lazy-load, I don't give IE users the option to switch the theme — they automatically get the light theme.

To make it work, I have the following code in my head section:

// 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 doesn't support classList, but I optionally load a polyfill if the visitor is using IE9.

To set up the switch function, I have the following code at the bottom of my page:

// 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();
});

Toggling the switch causes the page to reload the images, loading dark instead of light or vise versa.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM