主题一键切换
Media Query
初始NextJS项目后运行项目发现网页当前主题是黑暗模式,正和我电脑的主题匹配,打开白天模式后网页自动关闭暗黑模式。然后我在项目中发现了这几行代码:
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
body {
color: white;
background: black;
}
}
查了下 MND ,大致意思是使用媒体查询识别当前系统的主题。是否是暗黑模式。详见MDN
如果是 dark
模式则背景颜色调为黑色、字体调为白色。
CSS Variable
这里使用 CSS 变量来实现一键主题切换。
给跟 html 元素添加一个自定义属性。
注意,所有的 DOM 元素可以添加自定义属性的,自定义属性以 data-
开头,比如 data-theme
, data-props
。我们这里添加自定义属性 data-theme
到 html
元素上。
const html = document.getElementsByTagName('html')[0];
html.setAttribute('data-theme', 'dark');
然后定义相关 CSS 变量。变量根据不同的属性定义不同的值,这里使用 CSS 属性选择器。
// 当 html 元素的 data-theme 属性值为 dark 时的变量值
html[data-theme="dark"] {
--primary-color: #ffffff; // 主要的字体颜色
--primary-background-color: rgba(14, 14, 14, 1); // 主要的背景色
--secondary-background-color:#1D1D1D;
--footer-background-color: rgba(36, 36, 36, 1); // footer组件的背景色
--navbar-background-color: rgba(0, 0, 0, 0.5); // navbar组件的背景色
--secondary-color: rgba(255, 255, 255, 0.5); // 次一级,色值没那么显眼的字体颜色
--link-color: #34a8eb; // 链接 hover 上去的颜色
}
// 当 html 元素的 data-theme 属性值为 light 时的变量值
html[data-theme="light"] {
--primary-color: #333333;
--primary-background-color: rgba(255, 255, 255, 1);
--secondary-background-color: rgba(255, 255, 255, 1);
--footer-background-color: #f4f5f5;
--navbar-background-color: rgba(255, 255, 255, 0.5);
--secondary-color: #666666;
--link-color: #0070f3;
}
然后在相关使用颜色的 css 属性不直接给一定固定的颜色,而是给一个变量。
.header{
background-color: var(--primary-background-color);
color: var(--primary-color);
}
所以想改变主题直接改变 html 元素的 data-theme 属性的值就好。
const setTheme = (theme) => {
// ...
document.getElementsByTagName('html')[0].dataset.theme = theme; // 自定义属性可在元素的 dataset 对象里获取
}