一行代码切换暗黑模式:CSS变量与全局状态管理怎样结合

预设配色要求

两套主题风格为白版跟黑版,默认主题为白版;

变量 白版 黑板
主色 #E8302E #E9533E
警告色 #ED7F31 #ED7F31
字体色 #333333 #202022
背景色 #FFFFFF #252528
线条色 #252528 #D2D2D2

实现方案

1.scss混入器动态引入
  • 根据以上的预设配色要求,在前端实现可以动态切换系统的主题色。
  • 主要思路:给html跟标签设置data-theme属性,默认值为"light"。通过js动态改变主题标记data-theme属性(light、dark),配合scss混入器根据主题使用对应的系统变量,完成主体换肤。
  • styles文件夹下新建theme.scss文件,按照上面表格内的颜色方案定义两套主题,放置对应主题的颜色变量合集。

$themes: (
    light:(
    // 主题色
    --primary-color: "#E8302E";
    --success-color: "#009900";
    --warning-color: "#ED7F31";
    --danger-color: "#CD1706";
    // 字体颜色
    --font-color-primary: "#333333";
    --font-color-regular: "#757575";
    // 背景颜色
    --bg-color-primary: "#E8302E";
    --bg-color-content: "#FFFFFF";
    // 线条颜色
    --line-color-primary: "#D9D9D9";
    --line-color-divide: "#EEEEEE";
    ),
    dark:(
 // 主题色
    --primary-color: "#E9533E";
    --success-color: "#55A142";
    --warning-color: "#ED7F31";
    --danger-color: "#E71906";
    // 字体颜色
    --font-color-primary: "#D2D2D2";
    --font-color-regular: "#757575";
    // 背景颜色
    --bg-color-primary: "#202022";
    --bg-color-content: "#252528";
    // 线条颜色
    --line-color-primary: "#D2D2D2";
    --line-color-divide:  "#313131";
    )
)
  • styles文件夹下新建mixins.scss文件,如下配置:

@import "./theme.scss";
/**
    themeify:混入器t,用来获取data-theme的值。
    @each:遍历themes的键值对,$theme-name对应light/dark。$theme-map对应light/dark中的值。
    @content:用来在引用themeify时导入内容。如果data-theme=light,就会编译成[data-theme=light] .class {}
    themed:根据data-theme的值和$key到主题变量合集theme.scss文件中里获取颜色值。
*/
@mixin themeify {
 
    @each $theme-name,
    $theme-map in $themes {
        $theme-map: $theme-map  !global; // $theme-map为全局变量
 
        [data-theme="#{$theme-name}"] & {
            @content
        }
    }
}

@function themed($key) {
    @return map-get($theme-map, $key); // map-get($map,$key) 函数的作用是根据 $key,返回 $key 在 $map 中对应的值。比如themed(bgColor1)返回 #ffffff 或 #1a1a1a。
}
 
// 取背景色
@mixin get_bgcolor($color) {
    @include themeify {
        background-color: themed($color);
    }
}
 
// 字体、按钮/hover、其他颜色
@mixin get_text_color($color) {
    @include themeify {
        color: themed($color);
    }
}
 
// 边框色
@mixin get_border_color($color) {
    @include themeify{
        border: themed($color);
    }
}
  • 组件中使用方法:引入对应的混入器,传入theme.scss中定义的变量key;

.ai-btn-primary {
    @include get_bgcolor("primary-color");
 
    &:hover {
        @include get_bgcolor("red-hover-color")
    }
 
    &.ai-btn-disabled {
        &:hover {
            background-color: var(--ai-primary-color-3);
        }
    }
}
  • js切换主题:

window.document.documentElement.setAttribute( "data-theme","dark" );
2.切换整套主题样式
  • 定义主题样式变量,全局暴露

html,
html[data-theme="light"] {
    // 主题色
    --primary-color: var(--ai-primary-color-5);
    --success-color: var(--ai-success-color-3);
    --warning-color: var(--ai-primary-color-7);
    --danger-color: var(--ai-primary-color-2);
    // 字体颜色
    --font-color-primary: var(--ai-block-color-2);
    --font-color-regular: var(--ai-block-color-4);
    // 背景颜色
    --bg-color-primary: var(--ai-primary-color-5);
    --bg-color-content: var(--ai-white-color-1);
    // 线条颜色
    --line-color-primary: var(--ai-white-color-7);
    --line-color-divide: var(--ai-white-color-5);
}
html[data-theme="dark"] {
    // 主题色
    --primary-color: var(--ai-primary-color-12);
    --success-color: var(--ai-success-color-6);
    --warning-color: var(--ai-primary-color-7);
    --danger-color: var(--ai-primary-color-4);
    // 字体颜色
    --font-color-primary: var(--ai-block-color-7);
    --font-color-regular: var(--ai-block-color-4);
    // 背景颜色
    --bg-color-primary: var(--ai-block-color-11);
    --bg-color-content: var(--ai-block-color-12);
    // 线条颜色
    --line-color-primary: var(--ai-block-color-7);
    --line-color-divide: var(--ai-block-color-10); 
}
  • 切换主题,只需要一句代码即可完成:

window.document.documentElement.setAttribute( "data-theme","dark" );
posted @ 2025-05-18 12:22  Justus-  阅读(49)  评论(0)    收藏  举报