hugo优雅支持夜间模式
目录
周末补了个下午觉,睡醒后虽然很精神,毕竟白天睡太久,到晚上看屏幕有点刺眼,想着9ong.com也开启个夜间模式,自己看的时候,也舒服些。
想着应该就是一段简单的js和css,百度copy下代码放进去就可以了,但百度、google下,没有找到比较简洁优雅的方案,虽然思路方案大体一致,但觉得不够纯粹,自己在其他参考及hugo的基础上,结合自己的主题完成一个可以接受的demo。
想法
- 夜间模式样式
- 支持手动切换夜间与日间模式
- 初始化夜间模式,通过时间自动检测
- 初始化夜间模式,通过localstorage本地持久化获取
夜间模式样式
新增static/css/dark.css
html {
background-color: #171717 !important;
}
html {
filter: invert(100%) hue-rotate(180deg) brightness(105%) contrast(85%);
-webkit-filter: invert(100%) hue-rotate(180deg) brightness(105%) contrast(85%);
}
body {
background-color: #FFF !important;
}
img,
video,
body * [style*="background-image"] {
filter: hue-rotate(180deg) contrast(100%) invert(100%);
-webkit-filter: hue-rotate(180deg) contrast(100%) invert(100%);
}
由于我们在后面的js中使用到动态修改这个link标签的disabled值,所以我们破坏性的将link插入到了主题文件中的layouts\partials\script.html:
<!--夜间模式样式,来源谷歌浏览器插件-->
<link disabled id="dark-mode-theme" rel="stylesheet" href="/css/dark.css"></link>
可以根据自己的实际情况,看是要通过link来换肤,还是通过js中动态修改以上dark.css中的样式。找到自己舒适的操作,本文这个方式属于对主题文件的破坏性修改了,但目前对于我们自己的主题来说script.html就是用于加全局动态功能的文件,尽量不去改动其他布局html文件。
夜间模式手动切换按钮
<!--夜间模式手动切换-->
<li class="post-action" style="position: fixed;bottom: 20%;right: 4%;">
<a id="dark-mode-toggle" class="post-action-btn btn btn--default">
<i id="dark-mode-toggle-i" class="fa fa-moon-o"></i>
</a>
</li>
直接追加到script.html文件中,也是全局的一个按钮。
夜间模式js代码
直接追加到script.html文件中,在按钮有了之后执行。
//通过时间判断夜间模式,否则会完全手动切换并本地持久化模式,下次自动渲染本地持久化的模式
var darkMode = {
config:{
startHour:19,//19点开始
endHour:7,//7点结束
},
_darkTheme:null, //dark.css标签
_modeToggle:null, //手动切换按钮块
_modeToggleParent:null, //手动切换按钮wrap
_currentHour:0, //当前小时
_storageKey:"dark-mode-storage",
_storageByHandLastTIme:0, //上次手动设置模式时间 毫秒
_storageOverdueHours:12, //每隔12小时重新检查本地持久化
init:function(){
//夜间模式切换配置
this._modeToggleParent = document.getElementById("dark-mode-toggle");
this._modeToggle = document.getElementById("dark-mode-toggle-i");
this._darkTheme = document.getElementById("dark-mode-theme");
this._currentHour = new Date().getHours();
this.toggleListen();
this.initMode();
},
initMode:function(){
//初始化模式,来源本地持久化或自动检测模式
let initMode = this.getModeFromStorage() || this.autoMode();
this.setMode(initMode);
},
toggleListen:function(){
let _this = this;
//手动切换触发模式更改
this._modeToggleParent.addEventListener("click", () => {
if (this._modeToggle.className === "fa fa-moon-o") {
_this.setModeByHand("dark");
} else if (this._modeToggle.className === "fa fa-sun-o") {
_this.setModeByHand("light");
}
});
},
autoMode:function(){
let _currentHour = this._currentHour;
if(_currentHour > this.config.startHour || _currentHour < this.config.endHour){
return "dark";
}
return "light";
},
setMode:function(mode){
if (mode === "dark") {
this._darkTheme.disabled = false;
this._modeToggle.className = "fa fa-sun-o";
} else if (mode === "light") {
this._darkTheme.disabled = true;
this._modeToggle.className = "fa fa-moon-o";
}
},
setModeByHand:function(mode){
this.setMode(mode);
this.setModeToStorage(mode);
},
setModeToStorage:function(mode){
localStorage.setItem(this._storageKey, mode);
localStorage.setItem(this._storageKey+"-last-time", (new Date().getTime()));
},
getModeFromStorage:function(){
let _mode = localStorage.getItem(this._storageKey);
let _lastSetTime = localStorage.getItem(this._storageKey+"-last-time");
if(_mode && _lastSetTime){
_lastSetTime = _lastSetTime/1000;
let _currentTime = new Date().getTime()/1000;
let _overdueSeconds = this._storageOverdueHours * 3600;
if(_currentTime - _lastSetTime < _overdueSeconds){
return _mode;
}
}
localStorage.removeItem(this._storageKey);
localStorage.removeItem(this._storageKey+"-last-time");
return false;
},
};
darkMode.init();
效果
点击www.9ong.com右下日间与夜间模式切换按钮。
参考
Adding dark mode to a Hugo static website without learning CSS