zoukankan      html  css  js  c++  java
  • 利用CSS变量进行黑暗模式切换

    本文以react为例。

    用css变量来切换黑暗模式,易于维护和扩展。

    css变量的用法:

    .selector {
      --black-color: #282c34;
    }
    
    :root {
      --black-color: #282c34;
    }

    方案一

    设置主题对应的CSS变量,切换主题只需切换css属性的变量值。例如:切换APP元素的主题只需切换App的color和background-color对应CSS变量的变量值即可。

    :root {
      /* 模式切换变量,默认light模式 */
      --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 {
      /* 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;
    }
    
    .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;
      }
    }
    
    @media (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;
    }

    电脑刺绣绣花厂 http://www.szhdn.com 广州品牌设计公司https://www.houdianzi.com

    方案四

    利用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);
      };
    }, []);
  • 相关阅读:
    安装mysql到服务器的linux环境下
    Junit
    shell编程控制结构:expr、let、for、while、until、shift、if、case、break、continue、函数、select
    JavaScript组合继承的一点思考
    JavaScript-2.内置对象---简单脚本之弹出对话框显示当前时间 ---ShinePans
    Python之美[从菜鸟到高手]--2+2=5
    Flex中配置FusionCharts
    [WHY]Hello, Worktile~
    数据库学习之中的一个: 在 Oracle sql developer上执行SQL必知必会脚本
    Remove Nth Node From End of List
  • 原文地址:https://www.cnblogs.com/xiaonian8/p/13815284.html
Copyright © 2011-2022 走看看