多主题 切换方案
随着深色系慢慢渐入眼帘,现在多主题切换的方案越来越受欢迎了。接下来会列举几种多主题的实现方案。
# 方案 1
- 将影响主题的背景色/ 字体颜色/ 边框等 单独提取到一个文件中,同时配置不同的文件
- 通过动态加载来实现不同的主题
# 例如:
- public/light.css
/** 背景颜色 设置 */
.bk {
background: #ccc;
}
/** 字体颜色 设置 */
.fc {
color: red;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
- public/dark.css
/** 背景颜色 设置 */
.bk {
background: #f0f0f0;
}
/** 字体颜色 设置 */
.fc {
color: blue;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
- 通过以上实例,我们可以初期的时候通过 cdn 方式来加载
public/light.css
。- 用提取到属性来 标识特殊色值。比如使用
bk
来设置背景颜色- 点击按钮/ 或是切换主题的时候,通过 js 动态来加载
public/dark.css
。- 从而实现属性修改。 如果怕提取的的属性名称跟 内部名称重复的话,可以用一些特殊的命名方式来减少重复
- 或是使用一些局部作用域 以及影子 DOM 等方式来避免样式冲突都可以
- 但是个人感觉并不需要,首先影响主题的色值并不多,使用特殊的命名方式完全可以避免
# 方案 2
- 使用 css 中定义变量的方式来进行主题切换,其实大体的实现思想跟方案一相同。也是属性覆盖
- 可以参照下element-plus 方式
- 参照暗黑主题
这是大体说下实现思路,但是具体的实现办法可以看
element-plus
源码首先将影响到主题的所有的组件用到的颜色都单独提取出来定义成为变量. 看如下截图
可以按照自己主题的需求将用到的变量重新定义一遍,用来覆盖
新的主题颜色 以及直接覆盖老的主题颜色。也是可以通过 JavaScript 来动态加载重写的变量
这样就实现了主题切换
# 方案 3 (终极方案)
在介绍方案之前,先来介绍一个插件。是实现主题切换的重要手段。
# postcss-theme-rc
a postcss plugin, mainly used for page switching theme
- 转换结果
div a {
color: rc(A01);
background: red;
}
/* => */
div a {
color: #fff;
background: red;
}
html[data-theme-rc='light'] div a {
color: #fff;
}
html[data-theme-rc='dark'] div a {
color: black;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 如果我们想办法可以让代码编译的时候,给一组颜色以及主题。可以按照不同的主题来显示不同的颜色。是不是可以实现主题切换
- 例如上述编译结果。我们可以将
rc(A01)
来编译成为不同主题。 - 那么
rc(A01)
哪来的
const opts = {
colors: {
a: "#fff",
b: "black"
},
groups: {
A01: ["a", "b"]
},
themeSelector: ["light", "dark"]
};
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
colors
表示提供的所有的颜色色值。themeSelector
是不同的主题名称groups
就非常重要了。表示用哪种分组来参与颜色编译。key 值表示对外选择的。value 本身是一个数组,数组的中保存着颜色对应的 key 值。数组的个数跟主题数必须一一对应起来。- 例如 选择是分组
A01
的话,主题light
使用颜色#fff
. 主题dark
使用颜色black
。 - 所以只要参数符合规则,就可以实现多主题定义了
- 我们可以通过动态 js 来设置
html[data-theme-rc='dark']
的属性。这种模式类似于媒体查询。不同的属性下有着不同的颜色设置。 - 这种主题手段从编译层面已经开始介入了
- 个人觉得这种方案最为优雅。不知道诸位觉得呢???