今天小编跟大家讲解下有关利用CSS变量进行黑暗模式切换 ,相信小伙伴们对这个话题应该有所关注吧,小编也收集到了有关利用CSS变量进行黑暗模式切换 的相关资料,希望小伙伴们看了有所帮助。
本文以react为例。用css变量来切换黑暗模式,易于维护和扩展。
css变量的用法:
.selector { --black-color: #282c34;}:root { --black-color: #282c34;}方案一设置主题对应的css变量,切换主题只需切换css属性的变量值。例如:切换APP元素的主题只需切换App的color和background-color对应css变量的变量值即可。
:root { --current-background-color: var(--light-background-color); --current-primary-color: var(--light-primary-color); --light-primary-color: #666; --light-background-color: #fff; --dark-primary-color: #fff; --dark-background-color: #282c34;}.App { color: var(--current-primary-color); background-color: var(--current-background-color); min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: calc(10px + 2vmin); transition: background-color 0.3s;}那么如何切换:root下--current-background-color的值?
1. 查找它2. 替换它查它
// 找到:root下所有定义以--current变量const currentcssvar = Array.from(document.styleSheets).reduce( (acc, sheet) => (acc = [ ...acc, ...Array.from(sheet.cssRules).reduce( (def, rule) => (def = rule.selectorText ===":root"? [ ...def, ...Array.from(rule.style).filter((name) => name.startsWith("--current") ), ] : def), [] ), ]), []);换它
currentcssvar.forEach((item) => { document.documentElement.style.setProperty( item, `var(--${themeName}${item.substring(9)})` );});完整js代码:
import react, { useEffect, useState } from"react";import Project from"@bit/toringo.comp.product-list";import Switch from"@bit/campgladiator.cgui.components.atoms.switch";import"./App.css";import setTheme from"./util";// 默认主题可来源与server、storage等。const defaultTheme = 'light';function App() { const [mode, setMode] = useState(defaultTheme); useEffect(() => { setTheme(mode); }, [mode]); return ( <div className="App"> <Switch onClick={() => setMode(mode ==="dark"?"light":"dark")} /> <Project list={["Hulk","Stack","link"]} /> <a className="App-link"href="https://reactjs.org"target="_blank"rel="noopener noreferrer"> Learn react </a> </div> );}export default App;方案二设置css变量,定义theme对应的CSS class选择器,动态去改变className已达到主题切换。
.App { min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: calc(10px + 2vmin); transition: background-color 0.3s;}.App-light { color: var(--light-primary-color); background-color: var(--light-background-color);}.App-dark { color: var(--dark-primary-color); background-color: var(--dark-background-color);}js代码:
...<div className={`App ${mode ==="dark"?"App-dark":"App-light"}`}>.... 方案三利用css媒体查询动态改变网页主题样式,当浏览器的主体发生变化时, 媒体查询的prefers-color-scheme会动态执行匹配的规则,
@media (prefers-color-scheme: dark) { :root { --current-background-color: #282c34; --current-primary-color: #fff; [email protected] (prefers-color-scheme: light) { :root { --current-background-color: #fff; --current-primary-color: #282c34; }}.App { color: var(--current-primary-color); background-color: var(--current-background-color); min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; font-size: calc(10px + 2vmin); transition: background-color 0.3s;}方案四利用js事件监听媒体查询动态 改变网页主题样式,Web Animation API)还提供给了监听css媒体查询条件的匹配。
useEffect(() => { const mediaQuery = window.matchMedia("(prefers-color-scheme: light)"); const setFn = () => { setMode(mediaQuery.matches ?"light":"dark"); }; mediaQuery.addEventListener("change", setFn); return () => { mediaQuery.removeListener("change", setFn); };}, []);来源:爱蒂网