使用 Gatsby.js 搭建静态博客黑暗模式

更新日期: 2020-12-29阅读: 1.5k标签: 博客

没想到久违的 Gatsby 系列还能继续写,最近为博客更新了黑暗模式和手动切换功能,顺便记录下来。当然下面的实现方案不限于 Gatsby 使用,对于其他框架,思路都大同小异。


方案 1

最初实现的方案是直接使用媒体查询和 css 变量。关键是把区分两个模式的变量抽离出来,分别配置两组变量,核心代码如下:

@media screen and (prefers-color-scheme: dark) {
  :root {
    --linkColor: #ec9bab;
    --fontColor: #ecc3cb;
    --codeBlock: #3c495b;
    --code: #c3c7cb;
    --divider: #3e4b5e;
  }
}
@media screen and (prefers-color-scheme: light) {
  :root {
    --linkColor: #683741;
    --fontColor: hsl(284, 20%, 30%);
    --codeBlock: #3c495b;
    --code: #c3c7cb;
    --divider: #eee;
  }
}
body {
  background-color: var(--backgroundColor);
  color: var(--fontColor);
  transition: all 0.5s ease-in-out;
}

(prism 用户还要自己整理一下两个模式的 prism 样式)

CSS 变量除了在 IE 不能用之外其他浏览器的适应性还算不错,如果必须适配 IE 的话需要另外写一份不用变量的样式保底。


方案 2

按上面的写法其实已经可以实现根据系统配置转换明亮和黑暗模式,但是要做到直接在网页通过一个切换按钮手动修改还是远远不够,方案 2 登场。

因为现在 JavaScript 不能改变系统级的明暗模式,只能获取和监听模式变化,所以手动操作铁定不能靠 prefers-color-scheme 了。

我们需要反过来通过 JavaScript 获取 color-scheme 然后告诉 CSS 明暗模式发生变化,这样的变化包括系统级的改变用户在网页选择改变

首先把两组变量的作用范围改为 class:

.light-theme {
  --linkColor: #ec9bab;
  --fontColor: #ecc3cb;
  --codeBlock: #3c495b;
  --code: #c3c7cb;
  --divider: #3e4b5e;
}
.dark-theme {
  --linkColor: #683741;
  --fontColor: hsl(284, 20%, 30%);
  --codeBlock: #3c495b;
  --code: #c3c7cb;
  --divider: #eee;
}

下面这一段代码我写在 Layout.js 的 componentDidMount 中,只有这里才是服务器渲染的范围之外。

// setTheme 的实现
setTheme = themeName => {
  localStorage.setItem('theme', themeName)
  document.documentElement.className = themeName + '-theme'
  this.setState({
    theme: themeName,
  })
}
// 第一部分
let localTheme = localStorage.getItem('theme')
if (localTheme) {
  if (localTheme === 'dark') {
    this.setTheme('dark')
  } else {
    this.setTheme('light')
  }
} else if (window.matchMedia) {
  if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
    this.setTheme('dark')
  } else {
    this.setTheme('light')
  }
} else {
  // default light
  this.setTheme('light')
}
// 第二部分
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
darkModeMediaQuery.addListener(e => {
  const darkModeOn = e.matches
  if (darkModeOn) {
    this.setTheme('dark')
  } else {
    this.setTheme('light')
  }
})

先讲 setTheme 的实现:

数据持久化

实现设置整个文档的 class,然后 CSS 根据 class 配置变量(而不是方案 1 的媒体查询)

修改组件状态

第一部分是页面初始化时处理页面主题的逻辑:

首先查询有无被保存到 localstorage 的主题,有的话直接使用

没有的话使用 JavaScript 查询系统明暗方案,然后按系统配置设定

上面两种都不可行的情况下默认使用 light

第二部分是 JavaScript 监听系统明暗方案修改,响应式地改变页面的明暗方案(意味着不需要刷新页面)

剩下的切换按钮就没什么特别的,所以不放代码了。


hack

最后附带一个处理画面闪烁的方法。

虽然已经在样式添加 transition 属性,但是从 JavaScript 程序知道用户需要的明暗模式前仍然有一段空挡。如果用户选择了黑暗模式,就会造成画面先是明亮模式,然后几百毫秒后变为黑暗模式的尴尬局面。

我的解决方案是先把页面 display 设为 none,在判断并设置完页面 class 之后再将页面设为可见,这样就避免了画面闪烁,但是页面展示时间会慢一点点点点。

document.documentElement.style.display = 'none'
// 同步的判断程序
document.documentElement.style.display = 'block'
来自:https://ssshooter.com/2020-06-25-gatsby-blog-8/


链接: https://fly63.com/article/detial/10124

10个JavaScript难点:能够读懂这篇博客的JavaScript开发者,运气不会太差…

10个JavaScript难点包括:立即执行函数,闭包,使用闭包定义私有变量,prototype,模块化,变量提升,柯里化,apply, call与bind方法,Memoization,函数重载

流行的静态(博客)网站生成工具

最近特别流行使用静态网站搭建博客,本博客就是host在GitHub Pages的静态网站。静态网站非常适合专注于内容的网站,例如,博客

怎么选择确定个人博客网站的主题?

除非你的博客完全是为了满足自己的乐趣,否则你肯定希望获得读者。因此,考虑别人可能喜欢的内容非常重要。多年来我一直在关注博客圈,在吸引读者方面,有些方法确实非常有效,下面是一些选择博客主题的实用技巧

如何通过个人博客网站赚钱(最全方法)

几年前,我意识到很多开设个人网站的博主们正在赚钱,有些甚至赚取了巨额数字!他们中的很多人看起来很普通,就像你和我一样。那么,他们究竟是怎样做到的?你也可以通过博客赚钱吗?

网站web服务器个人博客站开通那些端口合适?

一般网站服务器,只需要开通80 443,(ssh端口默认22,,建议修改),ping命令没有端口,因为ICMP 协议没有到tcp层,仅走ip层,由于IP层协议是一种点对点的协议

如何选定搭建个人独立博客工具

身处当前数字化社会,打造个人品牌,越发显得重要(自我推销)。对于从事技相关的人群,欲要树立并长时间保持自己的个人品牌,最便捷的方法无疑是:坚持长时间高质量输出原创文章。就择取合适的博文平台,也是项技术活儿

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!