原文链接:https://geeknote.net/Rei/posts/400
最近在 GeekNote 上实现了深色主题,这里分享一下技术细节。
首先是如何管理深色主题的样式。一种做法是先写好浅色的主题样式,然后新增深色主题的样式:
// SCSS 代码
body {
background: #fcfcfd;
color: #19181b;
}
.button {
background: #543a92;
color: white;
}
.dark-mode {
color-scheme: dark; // 指示浏览器内置组件使用深色调
backgound: #19181b;
color: #e5e4e7;
.button {
background: #c3b6e2;
color: #2a1d49;
}
}
这样只要在 <body>
上添加 .dark-mode
样式就可以切换到深色主题:
<body class="dark-mode">
...
</body>
上面代码可以工作,但如果需要适配的组件有很多时会变得很复杂。我们需要一种方法抽颜色主题的公共部分,而不是一个个组件适配。
深色主题要修改的主要是各类颜色属性,我们可以把颜色属性抽取成 CSS 变量。
用 CSS 变量重构前面的 CSS:
:root {
--color-background: #fcfcfd;
--color-on-background: #19181b;
--color-primary: #543a92;
--color-on-primary: white;
}
.dark-mode {
color-scheme: dark;
--color-background: #19181b;
--color-on-background: #e5e4e7;
--color-primary: #c3b6e2;
--color-on-primary: #2a1d49;
}
body {
background: var(--color-background);
color: var(--color-on-background);
}
.button {
background: var(--color-primary);
color: var(--color-on-primary);
}
这样跟深色主题相关的内容都被集中到一个地方,修改组件样式的时候就不用考虑主题颜色。
前面的样式使用了 .dark-mode
作为是否应用深色主题的分界点,能不能自动适配用户设备的颜色偏好呢?答案是肯定的,现在主流浏览器已经支持了 prefers-color-scheme 这个媒体属性。
使用 prefers-color-scheme
重构前面的代码:
:root {
--color-background: #fcfcfd;
--color-on-background: #19181b;
--color-primary: #543a92;
--color-on-primary: white;
}
// mixin 是 SCSS 功能,用于抽取重复代码
@mixin dark-scheme {
--color-background: #19181b;
--color-on-background: #e5e4e7;
--color-primary: #c3b6e2;
--color-on-primary: #2a1d49;
}
.dark-mode {
color-scheme: dark;
@include dark-scheme;
}
@media (prefers-color-scheme: dark) {
:root {
@include dark-scheme;
}
}
body {
background: var(--color-background);
color: var(--color-on-background);
}
.button {
background: var(--color-primary);
color: var(--color-on-primary);
}
这样就可以实现默认情况下根据用户设备预设使用深色主题,在用户需要自定义的时候也可以通过 className 覆盖默认设置。
以上就是通过 CSS 变量和 Media Query 实现深色主题的方法。现在越来越多网站支持深色主题以满足不同的用户环境需求,如果你需要实现深色主题,不妨考虑用本文的方法管理 CSS。