前言
現在很多app 都已經實現了
夜間模式,這樣可以在夜間的時候保護我們的眼睛呢?於是,就有了給自己博客添加夜間模式的想法,花不多說,開始吧。
預覽
直接點擊按鈕 開啟/關閉夜間模式。
實現思路
本質上講,“夜間模式”就是在指定時間段內修改頁面配色、圖片亮度等,因此我們把問題拆開為三部分進行分析:
- 動態修改頁面配色、圖片亮度
- 在指定時間段內修改
- 具體的樣式內容
動態修改頁面配色、圖片亮度 既然提到了動態,就免不了要用到JavaScript了。
我們知道樣式有三種書寫形式,分別為外聯、內聯和內嵌。使用JS修改樣式,就要從這三個地方入手:
- 引入一個新的外聯CSS文件,以覆蓋原有樣式 /不影響原有樣式文件、方便維護/
- 不引入新的CSS,而是在原有CSS上追加樣式,以class名區分 /方便JS操作,實現優雅、方便維護/
- 在頁面中插入style標簽,在其中書寫樣式 /不增加HTTP連接數、方便維護/
- 修改元素的style屬性,即內嵌樣式 /不推薦/
第四種方法違反了“結構與表現分離的設計思想”,且內嵌樣式優先級過高
而且真正實現的話,需要對大量元素編寫JS代碼,執行效率低下,維護困難,因此一般不作考慮
前三種方法都有其適用場景,在這里選擇第二種
以class來區分樣式,實現了功能與表現的分離。對於JS代碼來說,問題變成了如何操作元素的class,而不必關心樣式的具體表現。
使用JS控制元素class
JS中Element.classList的add()和remove()方法,正好滿足我們的需求,且支持絕大多數瀏覽器(IE10以上支持)
但先別急着寫,還有一個細節:夜間模式這個狀態應被保存下來一直生效,或持續到本次會話結束,cookie可以滿足我們的要求
所以事情就很明朗了,編寫代碼:
function switchNightMode(){
var night = document.cookie.replace(/(?:(?:^|.*;\s*)night\s*\=\s*([^;]*).*$)|^.*$/, "$1") || '0';
if(night == '0'){
document.body.classList.add('night');
document.cookie = "night=1;path=/"
console.log('夜間模式開啟');
}else{
document.body.classList.remove('night');
document.cookie = "night=0;path=/"
console.log('夜間模式關閉');
}
}
即可實現夜間模式的切換和狀態保存。
在指定時間段內修改
思路很簡單,頁面加載后判斷時間,在指定范圍內修改元素class。這里有一個知識點立即調用函數
(function(){
if(document.cookie.replace(/(?:(?:^|.*;\s*)night\s*\=\s*([^;]*).*$)|^.*$/, "$1") === ''){
if(new Date().getHours() > 22 || new Date().getHours() < 6){
document.body.classList.add('night');
document.cookie = "night=1;path=/";
console.log('夜間模式開啟');
}else{
document.body.classList.remove('night');
document.cookie = "night=0;path=/";
console.log('夜間模式關閉');
}
}else{
var night = document.cookie.replace(/(?:(?:^|.*;\s*)night\s*\=\s*([^;]*).*$)|^.*$/, "$1") || '0';
if(night == '0'){
document.body.classList.remove('night');
}else if(night == '1'){
document.body.classList.add('night');
}
}
})();
具體的樣式內容
在上面的代碼中,我們控制了body的class,這是所有頁面元素的祖先元素。啟用夜間模式時,body的class值含有night
因此在編寫夜間模式的樣式時,在樣式選擇器前加body.night即可,可酌情使用!important
例如:
body.night{
background-color: #263238;
color: #aaa;
}
圖片亮度
使用CSS濾鏡中的brightness()濾鏡(僅支持現代瀏覽器)
body.night img {
filter: brightness(30%);
}
后端處理
因為是在本地通過JS操控樣式,所以在JS加載前后樣式不一樣,會導致頁面閃爍。
可在博客主題中加上判斷,滿足時間段及檢測到cookie含有相關字段后可直接輸出body class為night,如:
<body class="<?php echo($_COOKIE['night'] == '1' || date("H") > 22 || date("H") < 6 ? 'night' : ''); ?>">
關於夜間模式在博客園實現的簡單說明
只需要兩步就可以了,說明如下:
- 通過上面的代碼有兩個
js代碼塊 ,可以通過引用的方式引入,也可以通過寫在側邊欄(記得博客園側邊欄是支持js的,我沒有試過,請自行測試。) - 和上面的例子一樣,對應着自己寫夜間的css樣式。
版權聲明
部分資源引用於網絡。
Element.classList - Web API | MDN
給博客添加夜間模式
Document.cookie - Web API 接口 | MDN
filter - CSS | MDN
<style type="text/css">
input[type="button"] {
color: #353535;
text-shadow: 0 1px 0 #fff;
background-color: #f2f2f2;
border-color: #bfbfbf;
display: inline-block;
padding: 5px 12px;
margin-bottom: 0;
font-size: 13px;
font-weight: 400;
line-height: 1.53846154;
text-align: center;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 1px solid transparent;
border-radius: 4px;
-webkit-transition: all .4s cubic-bezier(.175,.885,.32,1);
-o-transition: all .4s cubic-bezier(.175,.885,.32,1);
transition: all .4s cubic-bezier(.175,.885,.32,1);
border-color: #bfbfbf;
}
</style>
