OverRainbow

theme switch

☕️ 1 min read

你可以从本文了解到

  • 夜间模式/主题切换

缘起

之所以想起“夜间模式”这个主题,是因为看到了这篇文章,而且这个主题已经躺在我的todoList里面很久了。

N种方式

我梳理了一下主要有以下几种主题切换方式

link.href切换

适用场景:没有采用预编译,样式可以通过文件级别隔离。

例如上面文章中的示例:

function switchSheet() {
  let theme = document.getElementById("theme");

  if (theme.getAttribute("href") == "light-mode.css") {
    theme.href = "dark-mode.css";
  } else {
    theme.href = "light-mode.css";
  }
}

styled-components ThemeProvider切换

适用场景:工程基于styled-components,样式采用全局theme值。

CSS var切换

适用场景:基于css module或者SCSS之类,样式可以采用全局定义的css variable,通过切换body的class进行切换。

以本blog工程的改造为例,示例如下:

/* index.module.css */
:global body.light{
  --bg: #fff;
  --textNormal: #222;
  --textTitle: black;
}
:global body.dark{
  --bg: #282c35;
  --textNormal: hsla(0,0%,100%,0.88);
  --textTitle: #fff;
  --primary-color: rgb(255, 167, 196);
}
:global body {
/* ... */
  background-color: var(--bg);
  color: var(--textNormal);
}
class ThemeService {
    constructor() {}
    // app挂载时读取并应用上次的theme
    syncTheme() {
        const theme = this.getTheme();
        document.body.setAttribute('class', theme);
    }
    // 设定theme并持久化
    setTheme(theme) {
        localStorage.setItem('theme', theme);
        document.body.setAttribute('class', theme);
    }
    // 读取定制的theme,给默认值light
    getTheme() {
        return localStorage.getItem('theme') || 'light';
    }
}

export default new ThemeService();