主流方案分为 2 种,1、css变量;2、如果考虑兼容性,则写2套class
借助css变量实现
原生css变量
在html标签上使用自定义属性进行标识
/* 暗色主题 */
html[data-theme='dark']{
--bg-color: #000;
}
/* 默认主题/浅色主题 */
:root{
--bg-color: #fff;
}
css选择器特定性(其实是浏览器计算样式权重的一种方式)
选择器的特殊性由选择器本身的组件确定。特殊性值表述为 4 个部分,如:0, 0, 0, 0。一个选择器的具体特殊性如下确定:
- 对于选择器中给定的各个 ID 属性值,加 0, 1, 0, 0。
- 对于选择器中给定的各个类属性值、属性选择或伪类,加 0, 0, 1, 0。
- 对于选择器中给定的各个元素和伪元素,加 0, 0, 0, 1。伪元素是否有特殊性?在这方面 CSS2 有些自相矛盾,不过 CSS2.1很清楚地指出,伪元素有特殊性,百且特殊性为 0, 0, 0, 1。
- 结合符和通配符选择器对特殊性没有任何贡献(后面还会更多地介绍这些值)。
例如,以下规则中选择器的特殊性见注释:
h1 { color: red; } /* specificity = 0, 0, 0, 1 */
p em { color: purple; } /* specificity = 0, 0, 0, 2 */
.grape ( color: purple } /* specificity = 0, 0, 1, 0 */
*.bright { color: yellow } /* specificity = 0, 0, 1, 0 */
p.bright em.dark { color: maroon} /* specificity = 0, 0, 2, 2 */
#id216 { color: blue; } /* specifity = 0, 1, 0, 0 */
div#sidebar *[href] { color: silver } /* 0, 1, 1, 1 */
所以上述主题间切换时,如果不想过分关注书写顺序,则需要注意css选择器特定性的计算,如添加html标签选择器,增加特殊性
用户点击切换主题时,通过js动态更改html标签上的data-theme的值
function toggle(theme)
document.documentElement.setAttribute('data-theme', theme);
}
此外可借助localStorage实现持久化。 定义一个变量key,每次主题变化时,进行存储,每次进入页面时从localStorage中取值。
less等预编译器
具体步骤如下:
- 使⽤ Less 预编译器来编译 Less ⽂件为 CSS ⽂件。
- 在 HTML ⽂件中引⼊编译后的 CSS ⽂件。
- 在 JavaScript 中动态修改 Less 变量的值。
- 使⽤ JavaScript 将新的 Less 变量值注⼊到编译后的 CSS ⽂件中。
- 将注⼊后的 CSS 样式应⽤到⻚⾯上。
// base.less ⽂件
@primary-color: #007bff; .btn {background-color: @primary-color; }
// dark.less ⽂件
@primary-color: #343a40;
function changeSkin() {
// 修改 Less 变量的值
less.modifyVars({'@primary-color': '#28a745' }).then(() => {
console.log('换肤成功');
}).catch(() => {console.error('换肤失败'); });
}
2种样式表,用户切换后,更换引入路径
function setTheme(theme = 'ligth') {
let link = document.querySelector('#theme-link');
let href = "/theme/" + theme + ".css";
if (!link) {
let head = document.querySelector('head');
link = document.createElement('link');
link.id = '#theme-link';
link.rel = "stylesheet";
link.href = href;
head.appendChild(link);
} else {
link.href = href;
}
}