Pure CSS allows the website to have the implementation code of dark mode switching function for free

Time:2021-10-21

preface

The concept of dark mode originated fromMacOS systemofMojave, provideLight themeandDark themeTwo kinds of skin for users to choose from,Dark themeThat’s what we often sayDiablo mode。 For the sake of eye health, the author chose mobile phones, tablets and computersDiablo mode

As apple officials gradually require that all major system platforms be adaptedDiablo modeTherefore, the author also explores a method that should beLowest cost on the marketofWebsite dark mode adaptation scheme

Friends who know the author should know that the author is a heavy CSS enthusiast. Of course, this time, we also use pure CSS to realize this scheme. Yes, without any JS, the side proves the power of CSS again.

thinking

The idea is simple. Use a button to switch theme styles back and forth. If the button is not selected, switch toLight themeIf the button is selected, switch toDark theme。 available:checkedand+Call to assist in completing the task.

:checked: select the selected form element

 +: sibling elements adjacent to an element

use<input>Analog button, triggered when the button is selected:checked, pass+Drive the main body of the adjacent website behind<div>get intoDiablo mode, exit when the status is checked or cancelledDiablo mode

<body>
    <input class="ios-switch" type="checkbox">
    < div class = "main" > website subject < / div >
</body>

For more functions and categories of selectors, please go back to the author’s article “can be”Can be the most complete and easy to remember CSS selector classification method》 。

Toggle button

I plan to design a beautiful button, but I don’t have a special idea. I open the iPhone and put the button in the settingToggle buttonImplement it with pure CSS.

Size and color are the same asIPhone toggle buttonagreement. The idea is to use<input>Analog button, declarationappearance:noneErase its default appearance and use::beforeSimulated background area, using::afterSimulate the click area when triggered:checkedAfter adding some small animation to decorate, it is almost perfectly realizedIPhone toggle button


<input class="ios-switch" type="checkbox">

.btn {
    border-radius: 31px;
    width: 102px;
    height: 62px;
    background-color: #e9e9eb;
}
.ios-switch {
    position: relative;
    appearance: none;
    cursor: pointer;
    transition: all 100ms;
    @extend .btn;
    &::before {
        position: absolute;
        content: "";
        transition: all 300ms cubic-bezier(.45, 1, .4, 1);
        @extend .btn;
    }
    &::after {
        position: absolute;
        left: 4px;
        top: 4px;
        border-radius: 27px;
        width: 54px;
        height: 54px;
        background-color: #fff;
        box-shadow: 1px 1px 5px rgba(#000, .3);
        content: "";
        transition: all 300ms cubic-bezier(.4, .4, .25, 1.35);
    }
    &:checked {
        background-color: #5eb662;
        &::before {
            transform: scale(0);
        }
        &::after {
            transform: translateX(40px);
        }
    }
}

Please stamphereView online demo and source code.

Diablo mode

Remember the whole network opening mourning mode on April 4? The author published an article《One line of code, the whole station enters mourning mode》, clever usefilterThis powerful CSS property.


html {
    filter:grayscale(1);
}

It’s really a line of code, and this time is no exception,One line of code, the whole station enters dark mode


html {
    filter: invert(1) hue-rotate(180deg);
}

filterThe compatibility of is not bad. You can rest assured to use it. There are still some details to pay attention to. This article will not repeat the explanation. You can review the details《One line of code, the whole station enters mourning mode》 。

filterIs a very magical attribute that canPhotoshopSome basic filter effects are applied to the website. I usually like to use it very muchfilter, in the author’s opinionCodePen There are many pure CSS effects used onfilter, careful students may find that the author particularly likes to use ithue-rotate()This function combinesCSS variablesDynamically generate transition colors. Please review the details《Use CSS variables to make your CSS more exciting》 。

This timeDiablo modeTwo filter functions are used:invert()hue-rotate()

invert(): invert, invert output image shading, value0%Then there is no change, and the value is0~100%Is a linear multiplier effect with a value of100%Then completely reverse

hue-rotate(): hue rotation, reduce image shading, and process non black and white colors. The value is0degThen there is no change, and the value is0~360degThen it gradually weakens and the value exceeds360degThen it is equivalent to calculating the remaining value around n turns

invert()The simple understanding isBlack turns white, white turns black, black and white is reversedhue-rotate()The simple understanding isDilute color。 To ensure that the theme hue does not change, declare the hue rotation as180degQuite reasonable.

According to the above analysis, it is used when the button is selected+The following sibling elements are also selected. If the sibling element has no background color, it needs to be declaredbackground-color:#fffOtherwise, the filter effect cannot take effect. In order to make the sibling element transition more naturally when using the filter effect, declaretransition:all 300ms


.ios-switch {
    ...
    &:checked {
        ...
        & + .main {
            filter: invert(1) hue-rotate(180deg);
        }
    }
}
.main {
    background-color: #fff;
    transition: all 300ms;
}

stayCodePen In order to better show the effect, use<iframe>Introduce our favorite Nuggets community and increase it for freeDiablo modeSwitching function: wink:. At the same time, a few changes have been made in the typesetting, please stamphereView online demo and source code.

optimization

Careful students may find that the pictures have become the feeling of B-ultrasound.

According to the design principle, skin changing is only for components. For example, some media elements, such as background, picture, video, etc., cannot be processed directly, and they need to be kept as they are. sinceDiablo modeIt is realized by using the inversion and hue rotation of the filter, so the inversion and hue rotation of the filter can be restored for these media elements again. UsedPhotoshop filterMy classmates should know better.


img,
video {
    filter: invert(1) hue-rotate(180deg);
}

Another question, how to deal with the background? As we all know, the background is to usebackgroundFamily attributes are declared, so they cannot be annotated through a specific selector. However, another way of thinking is to add a specific class name to the background element and include it in the above rules.

adoptChrome DevToolsseeNuggets communityIt is found that these avatars, thumbnails and display diagrams have some specific class names, and their specific class names are added to the rules.


img,
video,
.avatar,
.image,
.thumb {
    filter: invert(1) hue-rotate(180deg);
}

In general websites, this class name can be defined by itself. The most feasible way is to define a specific class name.exclude。 All elements without filter effect are added.exclude


.exclude {
    filter: invert(1) hue-rotate(180deg);
}

reform

In order to facilitate the demonstration of the above code, inCodePen Demo Use in<iframe>Introduce our favorite Nuggets community. Because the<iframe>Make a style declaration, so transfer to the Nuggets community throughChrome DevToolsDirect transformation.

stayChrome browserInside pressF12orCmd+Alt+IopenChrome DevTools, analyze the HTML structure of the website.


<body>
    <div id="__nuxt">...</div>
</body>

to<body>Insert inToggle button


<body>
    <input class="ios-switch" type="checkbox">
    <div id="__nuxt">...</div>
</body>

Put the followingSCSS codeconvert toCSS codeInsert into<head>New<style>Inside. Recommend an onlineSass to CSSofTools website, copy the following code to the website, directly convert it, and then paste it to the website<style>Inside.


.btn {
    border-radius: 31px;
    width: 102px;
    height: 62px;
    background-color: #e9e9eb;
}
.ios-switch {
    position: relative;
    appearance: none;
    cursor: pointer;
    transition: all 100ms;
    @extend .btn;
    &::before {
        position: absolute;
        content: "";
        transition: all 300ms cubic-bezier(.45, 1, .4, 1);
        @extend .btn;
    }
    &::after {
        position: absolute;
        left: 4px;
        top: 4px;
        border-radius: 27px;
        width: 54px;
        height: 54px;
        background-color: #fff;
        box-shadow: 1px 1px 5px rgba(#000, .3);
        content: "";
        transition: all 300ms cubic-bezier(.4, .4, .25, 1.35);
    }
    &:checked {
        background-color: #5eb662;
        &::before {
            transform: scale(0);
        }
        &::after {
            transform: translateX(40px);
        }
        & + #__nuxt {
            filter: invert(1) hue-rotate(180deg);
            img,
            video,
            .avatar,
            .image,
            .thumb {
                filter: invert(1) hue-rotate(180deg);
            }
        }
    }
}
#__nuxt {
    background-color: #fff;
    transition: all 300ms;
}

Found after completionToggle buttonNo, it can be passedposition:absolutePosition it absolutely where you want it to appear.


.ios-switch {
    position: absolute;
    right: 0;
    top: 0;
    z-index: 99999;
    outline: none;
}

Or in<div id="__nuxt">Create one anywhere in the<label>, by declaration<input class="ios-switch" id="toggle" hidden>and<label for="toggle">Bind to each other<input>Trigger area transferred to<label>Come on. How to realize it can refer to the author’s questionPure CSS tab navigation barrealization.

If you feel that the explanation is a little messy, you can sort it out and complete the above operation in three steps.

Open the Nuggets community website

PressF12orCmd+Alt+IopenChrome DevTools

to<head>Insert in<style>

In order to facilitate copying and pasting, the author compresses the CSS code obtained from the above analysis.


<style>.btn,.ios-switch::before,.ios-switch{border-radius:31px;width:102px;height:62px;background-color:#e9e9eb;}.ios-switch{position:relative;appearance:none;cursor:pointer;transition:all 100ms;}.ios-switch::before{position:absolute;content:"";transition:all 300ms cubic-bezier(0.45,1,0.4,1);}.ios-switch::after{position:absolute;left:4px;top:4px;border-radius:27px;width:54px;height:54px;background-color:#fff;box-shadow:1px 1px 5px rgba(0,0,0,0.3);content:"";transition:all 300ms cubic-bezier(0.4,0.4,0.25,1.35);}.ios-switch:checked{background-color:#5eb662;}.ios-switch:checked::before{transform:scale(0);}.ios-switch:checked::after{transform:translateX(40px);}.ios-switch:checked + #__nuxt{filter:invert(1) hue-rotate(180deg);}.ios-switch:checked + #__nuxt img,.ios-switch:checked + #__nuxt video,.ios-switch:checked + #__nuxt .avatar,.ios-switch:checked + #__nuxt .image,.ios-switch:checked + #__nuxt .thumb{filter:invert(1) hue-rotate(180deg);}#__nuxt{background-color:#fff;transition:all 300ms;}.ios-switch{position:absolute;right:0;top:0;z-index:99999;outline:none;}</style>

to<body>Insert in<input>


<body>
    <input class="ios-switch" type="checkbox">
    <div id="__nuxt">...</div>
</body>

In this way, a pure CSS implementation scheme can make the website instantly haveDiablo modeSwitch function, have you taken a new look at CSS again.

summary

wholePure CSS implementation schemeAround:checked+andfilterThree points are indispensable. It seems simple. It’s hard to imagine that a mere three click assistant can complete such a powerful function if CSS is not commonly used for special effects.

<body>
    <input class="ios-switch" type="checkbox">
    < div class = "main" > website subject < / div >
</body>

.ios-switch {
    ...
    &:checked {
        ...
        & + .main {
            filter: invert(1) hue-rotate(180deg);
            img,
            video,
            .exclude {
                filter: invert(1) hue-rotate(180deg);
            }
        }
    }
}
.main {
    background-color: #fff;
    transition: all 300ms;
}

Compared toCSS + JS implementation schemeIn general, there is no need to maintain a complete setDiablo modeStyle code, no action requiredDOM, there is no usual complex operation. Unless you want to make a complete set of highly customizedDiablo modeOnly one is neededCSS + JS implementation schemeOtherwise, use this scheme.

The scheme has the following characteristics.

  • Pure CSS implementation, simple and efficient, higher force grid
  • Almost no maintenance cost, fast iteration
  • Make full use of the filter effect and have good compatibility

It doesn’t hurt to try. When you’re done and feel that the effect is good, hurry to ask your boss for a raise: stuck_ out_ tongue_ winking_ Eye:, ha ha!

This is the end of this article about the implementation code of pure CSS to enable the website to have the dark mode switching function for free. For more content about CSS dark mode switching, please search the previous articles of developeppaer or continue to browse the relevant articles below. I hope you will support developeppaer in the future!