這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 核心 使用CSS變數, 準備兩套CSS顏色, 一套是在 light模式下的顏色,一套是在dark模式下的顏色 dark模式下的 CSS 權重要比 light 模式下的權重高, 不然當我們給html添加自定義屬性[data-theme='d ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
核心
- 使用CSS變數, 準備兩套CSS顏色, 一套是在 light模式下的顏色,一套是在dark模式下的顏色
- dark模式下的 CSS 權重要比 light 模式下的權重高, 不然當我們給html添加自定義屬性
[data-theme='dark']
的時候, dark模式權重比light低,會一直不起效果 - 當我們點擊 dark 模式的時候, 給 html 設置自定義屬性
[data-theme='dark']
- 當我們點擊 light 模式的時候, 給 html 設置自定義屬性
[data-theme='light']
- 在 dark 模式下, 會匹配到
html[data-theme='dark']
選擇器下的樣式 - 在 light 模式下,由於我們沒有設置
html[data-theme='light']
的方案, 那麼他就匹配:root(即html)下的樣式
兩套樣式代碼大概如下(列了一部分):
:root { --color-body-bg: #ffffff; --color-text: #000; --color-secondary-bg-for-transparent: rgba(209, 209, 214, 0.28); } html[data-theme='dark'] { --color-body-bg: #222222; --color-text: #ffffff; --color-primary-bg-for-transparent: rgba(255, 255, 255, 0.12); }然後我們點擊的時候,通過
let theme = 'light' // light / dark document.documentElement.setAttribute('data-theme', theme)
這樣就能實現簡單的更換膚色功能了
什麼? 你以為這就完了?好戲剛開始
跟隨系統顏色
首先利用Window
的 'matchMedia()' 方法返回一個新的 MediaQueryList
對象,表示指定的媒體查詢 (en-US)字元串解析後的結果。
如運行媒體查詢(max-width: 600px)
併在<span>
;中顯示MediaQueryList
的matches
屬性值。如果視口的寬度小於或等於 600 像素,則輸出將為 true,而如果視窗的寬度大於此寬度,則將輸出 false。
<span class="mq-value"></span>
let mql = window.matchMedia('(max-width: 600px)'); document.querySelector(".mq-value").innerText = mql.matches; //此時小於或等於600像素時span 裡面的結果為false
利用prefers-color-scheme
[CSS媒體特性] 用於檢測用戶是否有將系統的主題色設置為亮色或者暗色。
.day { background: #eee; color: black; } .night { background: #333; color: white; } @media (prefers-color-scheme: dark) { .day.dark-scheme { background: #333; color: white; } .night.dark-scheme { background: black; color: #ddd; } } @media (prefers-color-scheme: light) { .day.light-scheme { background: white; color: #555; } .night.light-scheme { background: #eee; color: black; } }
兩者相結合
把matchMedia()
和prefers-color-scheme
結合在一起, 我們就可以通過 js 去給系統顏色為dark或 light 的情況下更換對應的 html自定義屬性, 即[data-theme='dark']
或 [data-theme='light']
首先,我們先去獲取主題顏色, 我們還沒設置的時候,就預設是系統顏色, 設置了就把他存儲起來,下次直接獲取這個顏色
// 獲取主題變數 let appearance = ref<string>(localStorage.getItem('appearance') || 'auto') // 查詢當前系統主題顏色 const match = window.matchMedia("(prefers-color-scheme: dark)") // 如果主題變數為 auto, 則跟隨系統主題 if (appearance.value === 'auto') { followSystem() } else { document.documentElement.setAttribute('data-theme', appearance.value) } function followSystem() { // 當前系統顏色是亮色還是暗色 , 設置對應的html[data-theme= 'dark' 或者'light'] const theme = match.matches ? 'dark' : 'light' document.documentElement.setAttribute('data-theme', theme) } // 監聽系統主題變化,電腦主題發生改變的時候就調用followSystem函數 match.addEventListener('change', followSystem)
封裝成一個hooks
暴露出一個 useThemeColor函數, 返回一個對象, 對象裡面返回我們的主題變數
/ 獲取主題變數 let appearance = ref<string>(localStorage.getItem('appearance') || 'auto') // 查詢當前系統主題顏色 const match:MediaQueryList = window.matchMedia("(prefers-color-scheme: dark)") // 監聽系統主題變化 match.addEventListener('change', followSystem) function followSystem() { const theme = match.matches ? 'dark' : 'light' document.documentElement.setAttribute('data-theme', theme) } watchEffect(() => { // 如果主題變數為 auto, 則跟隨系統主題 if (appearance.value === 'auto') { followSystem() } else { document.documentElement.setAttribute('data-theme', appearance.value) } }) export default function useThemeColor() { return { appearance, } }
使用hooks
導入我們export出來的函數
import useThemeColor from '../hooks/useThemeColor'
使用函數,註意, 這裡返回的 apprance 已經是一個響應式數據了
const { appearance } = useThemeColor()
使用 v-model 綁定apprance,直接使用apprance , 當我們切換顏色的時候, 就會調用watchEffect裡面的函數, 達到一鍵換膚效果
<div class="item"> <div class="left"> <div class="title">外觀</div> </div> <div class="right"> <select v-model="appearance"> <option value="auto">{{ "自動" }}</option> <option value="light">