Pure CSS free implementation code for websites to have dark mode switching function

Pure CSS free implementation code for websites to have dark mode switching function

Preface

The concept of dark mode originated from Mojave of MacOS系統, which provides two skins for users to choose from:淺色主題and深色主題.深色主題is what we often call暗黑模式. For the sake of eye health, I chose暗黑模式on my phone, tablet and computer.

As Apple officials gradually require all major system platforms to adapt to暗黑模式, the author has also explored a網站暗黑模式適配方案that should be the lowest cost on the market .

Friends who know me should all know that I am a heavy CSS enthusiast. Of course, this time I also use pure CSS to implement this solution. Yes, without adding any JS, the power of CSS is once again proved.

Ideas

The idea is simple, use a button to switch back and forth between theme styles. If the button is unchecked, it switches to淺色主題; if the button is checked, it switches to深色主題. You can use :checked and + hit to assist in completing this task.

:checked : The form element with the option checked

+ : adjacent sibling elements of an element

Use <input> to simulate a button. When the button is in the selected state, it triggers :checked . Through + , the adjacent website body <div> behind it enters暗黑模式. When the selected state is canceled,暗黑模式is exited.

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

For more selector functions and classifications, please refer to my article "Probably the most complete and easiest to remember CSS selector classification method".

Toggle Button

I wanted to design a nice-looking button, but I had no particular ideas, so I opened my iPhone and implemented切換按鈕in the settings using pure CSS.

The size and color are consistent with the iPhone switch button . The idea is to use <input> to simulate a button, declare appearance:none to erase its default appearance, use ::before to simulate the background area, use ::after to simulate the click area, and add some small animations for modification after triggering :checked , thus realizing iPhone切換按鈕almost perfectly.

<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 click here to view the online demo and source code.

Dark Mode

Do you remember the time on April 4 when the entire Internet went into mourning mode? The author published an article "One line of code puts the entire site into mourning mode", cleverly using the powerful CSS attribute filter .

html {
    filter:grayscale(1);
}

It really is just one line of code, and this time is no exception.一行代碼全站進入暗黑模式.

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

The compatibility of filter is not bad, and students can use it with confidence. There are still some details that need to be paid attention to, which will not be repeated in this article. For details, please refer to "One line of code puts the whole site into mourning mode".

filter is a very magical property that can apply some basic filter effects Photoshop to the website. I usually like to use filter . There are many pure CSS special effects on my CodePen that use filter . Careful students may find that I particularly like to use the hue-rotate() function combined with CSS變量to dynamically generate transition colors. For details, please refer to "Use CSS variables to make your CSS more exciting".

This暗黑模式uses two filter functions: invert() and hue-rotate() .

invert() : Inverts the image and outputs it in reverse. A value of 0% means no change, a value of 0~100% means a linear multiplier effect, and a value of 100% means a complete inversion

hue-rotate() : hue rotation, weakening image coloring, processing non-black and white colors, a value of 0deg means no change, a value of 0~360deg means gradual weakening, and a value exceeding 360deg means N circles and then calculating the remaining value

invert() can be simply understood as黑變白,白變黑,黑白顛倒. hue-rotate() can be simply understood as沖淡顏色. To ensure that the theme hue does not change, it is reasonable to declare the hue rotation to be 180deg .

According to the above analysis, when the button is in the selected state, use + to make the following sibling elements also enter the selected state. If the sibling element has no background color background-color:#fff must be declared, otherwise the filter effect will not take effect. In order to make the transition of this sibling element more natural when using the filter effect, declare transition:all 300ms .

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

In order to better demonstrate the effect on CodePen, we use <iframe> to introduce our favorite Nuggets community and add暗黑模式switching function for free:wink:. At the same time, some minor changes were made to the layout. Please click here to view the online demo and source code.

optimization

Careful students may find that the pictures all look like ultrasound photos.

According to design principles, skinning only targets components. Some media elements, such as backgrounds, pictures, videos, etc., cannot be processed directly and need to remain as they are. Since暗黑模式is achieved by using the inversion and hue rotation of the filter, it can be restored by reapplying the inversion and hue rotation of the filter to these media elements. Students who have used Photoshop濾鏡should know it better.

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

Another question is, how to deal with the background? As we all know, backgrounds are declared using background family of properties, so they cannot be marked with a specific selector. However, you can think of it another way, that is, to add a specific class name to the element with background and include it in the above rules.

By viewing the website source code of掘金社區through Chrome DevTools , we found that these avatars, thumbnails, and display images all 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 a general website, this class name can be defined by yourself. The most feasible way is to define a specific class .exclude . Add .exclude to all elements that do not use filter effects.

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

Renovation

In order to facilitate the demonstration of the code, we use <iframe> in CodePen Demo to introduce our favorite Nuggets community. Since it is impossible to declare styles for <iframe> , we moved to the Nuggets community and modified it directly through Chrome DevTools .

Press F12 or Cmd+Alt+I in Chrome瀏覽器to open Chrome DevTools and analyze the HTML structure of the website.

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

Insert切換按鈕into <body> .

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

Convert the following SCSS代碼into CSS代碼and insert it into the newly created <style> in <head> . I recommend an online SASS轉CSS tool website. Copy the following code to the website for direct conversion, and then paste it into <style> after completion.

.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;
}

After completion, if切換按鈕does not appear, you can use position:absolute to absolutely position it to the position where you want it to be displayed.

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

Or create a <label> anywhere in <div id="__nuxt"> , and bind <input class="ios-switch" id="toggle" hidden> and <label for="toggle"> to each other to transfer the trigger area of <input> to <label> . For specific implementation methods, please refer to the author's pure CSS tab navigation bar implementation.

If you feel the explanation is a bit confusing, you can tidy it up a bit and complete the above operations in three steps.

Open the Nuggets Community website

Press F12 or Cmd+Alt+I to open Chrome DevTools

Insert <style> into <head>

In order to facilitate copying and pasting, the author compressed 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>

Insert <input> into <body>

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

Just like that, a pure CSS implementation can make the website instantly have暗黑模式switching function. Does it make you look at CSS with new eyes?

Summarize

The entire純CSS實現方案revolves around three points :checked , + and filter , none of which can be missing. It seems simple. If CSS is not commonly used for special effects, it is hard to imagine that such a powerful function can be accomplished with just three auxiliary points.

<body>
    <input class="ios-switch" type="checkbox">
    <div class="main">Website body</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 with CSS+JS實現方案, there is no need to maintain a complete set of暗黑模式style codes, no need to operate DOM , and no usual complicated operations. Unless you want to make a complete set of highly customized暗黑模式, you need a CSS+JS實現方案, otherwise you can use this solution.

This solution has the following features.

  • Pure CSS implementation, simple and efficient, more stylish
  • Almost no maintenance cost, fast iteration
  • Make full use of filter effects and have good compatibility

It’s okay to give it a try. Once you’ve finished and think the results are good, go ask your boss for a raise:stuck_out_tongue_winking_eye:, haha!

This concludes this article about how to use pure CSS to enable dark mode switching for websites for free. For more information about CSS dark mode switching, please search previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope you will support 123WORDPRESS.COM in the future!

<<:  JavaScript realizes the drag effect of modal box

>>:  Solution to the IP address not being displayed under Linux

Recommend

The basic use of html includes links, style sheets, span and div, etc.

1. Links Hypertext links are very important in HTM...

Implementation of check constraints in MySQL 8.0

Hello everyone, I am Tony, a teacher who only tal...

The implementation of Youda's new petite-vue

Table of contents Preface Introduction Live Easy ...

Python MySQL database table modification and query

Python connects to MySQL to modify and query data...

Scary Halloween Linux Commands

Even though it's not Halloween, it's wort...

CSS3 realizes various graphic effects of small arrows

It’s great to use CSS to realize various graphics...

Experience of redesigning the homepage of TOM.COM

<br />Without any warning, I saw news on cnB...

How to build your own Angular component library with DevUI

Table of contents Preface Creating a component li...

Advanced crawler - Use of Scrapy_splash component for JS automatic rendering

Table of contents 1. What is scrapy_splash? 2. Th...

Vue keeps the user logged in (various token storage methods)

Table of contents How to set cookies Disadvantage...

How to isolate users in docker containers

In the previous article "Understanding UID a...

HTML table tag tutorial (31): cell width and height attributes WIDTH, HEIGHT

By default, the width and height of the cell are ...