一行代码切换暗黑模式: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" );

浙公网安备 33010602011771号