純CSS免費(fèi)讓網(wǎng)站擁有暗黑模式切換功能的實(shí)現(xiàn)代碼

前言
暗黑模式這個(gè)概念最早起源于 MacOS系統(tǒng)
的 Mojave
,提供 淺色主題
和 深色主題
兩種皮膚供用戶選擇, 深色主題
就是我們常說的 暗黑模式
。為了眼睛健康,筆者在手機(jī)、平板和電腦上都選擇了 暗黑模式
。
隨著蘋果官方逐漸要求各大系統(tǒng)平臺都得適配 暗黑模式
,所以筆者也探索出一種應(yīng)該是 市面上最低成本 的 網(wǎng)站暗黑模式適配方案
。
認(rèn)識筆者的朋友應(yīng)該都知道筆者是一位重度CSS發(fā)燒友,當(dāng)然這次也是使用純CSS實(shí)現(xiàn)這個(gè)方案。是的,不加任何一段JS,側(cè)面再次證明CSS的強(qiáng)大。
思路
思路很簡單,使用一個(gè)按鈕來回切換主題樣式。按鈕未選中則切換到 淺色主題
,按鈕選中則切換到 深色主題
??捎?:checked
和 +
打輔助完成這個(gè)任務(wù)。
:checked :選項(xiàng)選中的表單元素
+ :元素相鄰的同胞元素
使用 <input>
模擬按鈕,當(dāng)按鈕處于選中狀態(tài)時(shí)觸發(fā) :checked
,通過 +
帶動(dòng)后面相鄰的網(wǎng)站主體 <div>
進(jìn)入 暗黑模式
,選中狀態(tài)取消時(shí)則退出 暗黑模式
。
<body> <input class="ios-switch" type="checkbox"> <div class="main">網(wǎng)站主體</div> </body>
更多選擇器的功能和分類請回看筆者這篇文章 《可能是最全最易記的CSS選擇器分類大法》 。
切換按鈕
打算設(shè)計(jì)一個(gè)美觀的按鈕,可是沒有特別思路,就打開iPhone,把設(shè)置里的 切換按鈕
用純CSS實(shí)現(xiàn)一番。
尺寸和顏色都是與 iPhone切換按鈕 一致。思路是使用 <input>
模擬按鈕,聲明 appearance:none
將其默認(rèn)外觀抹去,使用 ::before
模擬背景區(qū)域,使用 ::after
模擬點(diǎn)擊區(qū)域,在觸發(fā) :checked
后添加一些小動(dòng)畫進(jìn)行修飾,近乎完美地實(shí)現(xiàn)了 iPhone切換按鈕
。
<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); } } }
請戳 這里 查看在線演示與源碼。
暗黑模式
還記得4月4日那次全網(wǎng)開啟悼念模式嗎?筆者發(fā)表了一篇文章 《一行代碼全站進(jìn)入悼念模式》 ,巧妙地使用 filter
這個(gè)強(qiáng)大的CSS屬性。
html { filter:grayscale(1); }
真的是一行代碼,本次也不例外, 一行代碼全站進(jìn)入暗黑模式
。
html { filter: invert(1) hue-rotate(180deg); }
filter
的兼容性不差,各位同學(xué)可放心使用,還有一些細(xì)節(jié)地方需注意,本文就不重復(fù)講解了,詳情可回看 《一行代碼全站進(jìn)入悼念模式》 。
filter
是一個(gè)非常神奇的屬性,能將 Photoshop
一些基礎(chǔ)的濾鏡效果應(yīng)用到網(wǎng)站上。筆者平時(shí)非常喜歡使用 filter
,在筆者的CodePen 上有許多純CSS特效都使用了 filter
,細(xì)心的同學(xué)可能會發(fā)現(xiàn)筆者特別喜歡使用 hue-rotate()
這個(gè)函數(shù)結(jié)合 CSS變量
動(dòng)態(tài)生成過渡顏色,詳情請回看 《妙用CSS變量,讓你的CSS變得更心動(dòng)》 。
本次的 暗黑模式
使用到兩個(gè)濾鏡函數(shù): invert()
、 hue-rotate()
。
invert() :反相,反向輸出圖像著色,值為 0%
則無變化,值為 0~100%
則是線性乘子效果,值為 100%
則完全反轉(zhuǎn)
hue-rotate() :色相旋轉(zhuǎn),減弱圖像著色,處理非黑白的顏色,值為 0deg
則無變化,值為 0~360deg
則逐漸減弱,值超過 360deg
則相當(dāng)繞N圈再計(jì)算剩余的值
invert()
簡單理解就是 黑變白,白變黑,黑白顛倒
。 hue-rotate()
簡單理解就是 沖淡顏色
。為了確保主題色調(diào)不會改變,將色相旋轉(zhuǎn)聲明為 180deg
比較合理。
依據(jù)上述分析的思路,當(dāng)按鈕處于選中狀態(tài)時(shí)使用 +
連帶后面的同胞元素也進(jìn)入選中狀態(tài)。若同胞元素?zé)o背景色需聲明 background-color:#fff
,否則無法讓濾鏡效果起效,為了讓這個(gè)同胞元素在使用濾鏡效果時(shí)過渡得更自然,聲明 transition:all 300ms
。
.ios-switch { ... &:checked { ... & + .main { filter: invert(1) hue-rotate(180deg); } } } .main { background-color: #fff; transition: all 300ms; }
在 CodePen 上為了更好地展示效果,就使用 <iframe>
引入我們最愛的 掘金社區(qū) ,免費(fèi)為其增加 暗黑模式
切換功能:wink:。同時(shí)在排版上做了少量修改,請戳 這里 查看在線演示與源碼。
優(yōu)化
細(xì)心的同學(xué)可能會發(fā)現(xiàn),怎么圖片都變成照B超的感覺了。
按照設(shè)計(jì)原則來說,換膚只針對組件,像一些媒體類型的元素,例如背景、圖片、視頻等,都是不能直接處理的,需保持其原樣。既然 暗黑模式
是使用了濾鏡的反相和色相旋轉(zhuǎn)實(shí)現(xiàn),那么對這些媒體元素再次使用濾鏡的反相和色相旋轉(zhuǎn)就能復(fù)原了。使用過 Photoshop濾鏡
的同學(xué)應(yīng)該會更清楚。
img, video { filter: invert(1) hue-rotate(180deg); }
還有一個(gè)問題,背景怎樣處理?眾所周知,背景是使用 background
系列屬性進(jìn)行聲明的,因此無法通過特定的選擇器進(jìn)行標(biāo)注。但是,可換種思路處理,就是給有背景的元素加上一個(gè)特定類名,將其包含到上述規(guī)則里即可。
通過 Chrome DevTools
查看 掘金社區(qū)
的網(wǎng)站源碼,發(fā)現(xiàn)這些頭像、縮略圖和展示圖都有一些特定類名,將其特定類名添加到規(guī)則里。
img, video, .avatar, .image, .thumb { filter: invert(1) hue-rotate(180deg); }
在通用網(wǎng)站里,這個(gè)類名可自行定義,最可行的方法就是定義一個(gè)特定類名 .exclude
。不使用濾鏡效果的元素統(tǒng)統(tǒng)加上 .exclude
。
.exclude { filter: invert(1) hue-rotate(180deg); }
改造
上述為了方便演示代碼,在 CodePen Demo 里使用 <iframe>
引入我們最愛的 掘金社區(qū) 。由于無法對 <iframe>
進(jìn)行樣式聲明,所以轉(zhuǎn)移到 掘金社區(qū) 上,通過 Chrome DevTools
直接改造。
在 Chrome瀏覽器
里按 F12
或 Cmd+Alt+I
打開 Chrome DevTools
,分析網(wǎng)站的HTML結(jié)構(gòu)。
<body> <div id="__nuxt">...</div> </body>
往 <body>
里插入 切換按鈕
。
<body> <input class="ios-switch" type="checkbox"> <div id="__nuxt">...</div> </body>
把以下 SCSS代碼
轉(zhuǎn)換成 CSS代碼
插入到 <head>
新建的 <style>
里。推薦一個(gè)在線 SASS轉(zhuǎn)CSS
的 工具網(wǎng)站 ,復(fù)制以下代碼到網(wǎng)站里直接轉(zhuǎn)換,完成后再貼到 <style>
里。
.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; }
完成后發(fā)現(xiàn) 切換按鈕
沒有出現(xiàn),可通過 position:absolute
將其絕對定位到想要顯示的位置。
.ios-switch { position: absolute; right: 0; top: 0; z-index: 99999; outline: none; }
或在 <div id="__nuxt">
里任意地方創(chuàng)建一個(gè) <label>
,通過聲明 <input class="ios-switch" id="toggle" hidden>
和 <label for="toggle">
互相綁定,將 <input>
的觸發(fā)區(qū)域轉(zhuǎn)移到 <label>
上。具體怎樣實(shí)現(xiàn),可參照筆者這個(gè) 純CSS標(biāo)簽導(dǎo)航欄 實(shí)現(xiàn)。
若覺得講解有點(diǎn)亂,可稍作整理,三步完成上述操作。
打開掘金社區(qū)網(wǎng)站
按 F12
或 Cmd+Alt+I
打開 Chrome DevTools
往 <head>
里插入 <style>
為了方便復(fù)制粘貼,筆者將上述分析得出的CSS代碼進(jìn)行壓縮。
<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>
往 <body>
里插入 <input>
<body> <input class="ios-switch" type="checkbox"> <div id="__nuxt">...</div> </body>
就這樣,一個(gè)純CSS的實(shí)現(xiàn)方案就能讓網(wǎng)站瞬間擁有 暗黑模式
切換功能,有沒有又對CSS刮目相看了。
總結(jié)
整個(gè) 純CSS實(shí)現(xiàn)方案
圍繞著 :checked
、 +
和 filter
三個(gè)點(diǎn)進(jìn)行,缺一不可??此坪唵?,若不是常用CSS做特效也很難想象出區(qū)區(qū)三個(gè)點(diǎn)打輔助也能完成一個(gè)這么強(qiáng)大的功能。
<body> <input class="ios-switch" type="checkbox"> <div class="main">網(wǎng)站主體</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; }
相比于 CSS+JS實(shí)現(xiàn)方案
而言,無需維護(hù)一整套 暗黑模式
樣式代碼,無需操作 DOM
,沒有了往常復(fù)雜的操作。除非要做一整套高度定制的 暗黑模式
才需一個(gè) CSS+JS實(shí)現(xiàn)方案
,否則用該方案即可。
本方案具有以下特點(diǎn)。
- 純CSS實(shí)現(xiàn),簡單高效,逼格更高
- 幾乎沒有維護(hù)成本,快速迭代
- 充分利用濾鏡效果,兼容性好
試試無妨,完成了覺得效果不錯(cuò)就趕緊找你老板加薪去:stuck_out_tongue_winking_eye:,哈哈!
到此這篇關(guān)于純CSS免費(fèi)讓網(wǎng)站擁有暗黑模式切換功能的實(shí)現(xiàn)代碼的文章就介紹到這了,更多相關(guān)CSS暗黑模式切換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
- 這篇文章主要介紹了CSS變量實(shí)現(xiàn)暗黑模式的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)2020-03-16
- 這篇文章主要介紹了Html頁面支持暗黑模式的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)2019-12-26
詳解Html5項(xiàng)目適配系統(tǒng)深色模式方案總結(jié)
這篇文章主要介紹了詳解Html5項(xiàng)目適配系統(tǒng)深色模式方案總結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一2021-04-14