用 Tailwind CSS 讓你的網站進入深色模式
深色模式是現在許多作業系統都有的超夯功能,幫你的網站設計出一個深色的主題是勢在必行的。
為了使你的改造之路變得更加輕鬆愉快,Tailwind 本身就提供了一個叫做 dark
的模式變化,當瀏覽器或作業系統開啟深色模式時,你的網站可以有不同的樣式。
<div class="bg-white dark:bg-gray-800">
<h1 class="text-gray-900 dark:text-white">這裡是深色模式 !</h1>
<p class="text-gray-600 dark:text-gray-300">
Lorem ipsum...
</p>
</div>
但這邊有一件事情要注意一下,因為檔案大小的關係,在 Tailwind 中深色模式的狀態判斷預設是關閉的。
如果要打開深色模式,請把你 tailwind.config.js
裡 darkMode
選項的值改成 media
。
// tailwind.config.js
module.exports = {
darkMode: 'media',
// ...
}
現在,只要使用者的作業系統有開啟深色模式,那麼有 dark:
開頭的這些類別都會蓋過自己原本的樣式。其實 media
就是在背後使用了 色彩偏好方案
(prefers-color-scheme),但是如果你想要手動切換深色模式的效果,你可以使用 class 參數 來控制它。
一般來說,開啟 darkMode
只會幫你把跟顏色有關的 class (類別) 增加 dark
的狀態判斷,像是文字顏色、背景顏色、邊框顏色、漸層和 placeholder 的顏色。
dark
的變化模式也能與其它的變化搭在一起使用,比如響應式變化,和狀態變化模式 (像是 hover 和 focus):
<button class="lg:dark:hover:bg-white ...">
<!-- ... -->
</button>
響應式變化需要放在第一個,接著是 dark
,狀態變化要放在最後面,這樣才能正常運作。
如果要幫其它的 功能
(utilities) 打開 dark
的模式變化,只需要在變化模式的清單中,幫你想要開啟深色模式的功能加上 dark
參數,像是:
// tailwind.config.js
module.exports = {
// ...
variants: {
extend: {
textOpacity: ['dark']
}
}
}
在預設情況下, dark
的模式變化只會幫 backgroundColor
, borderColor
, gradientColorStops
, placeholderColor
, and textColor
這幾個 功能 (Utilities) 開啟。
如果你想要跟系統的偏好設定不一樣、能夠讓你手動切換深色模式的話,那麼你就要使用 class
這個參數,來取代原本的 media
。
// tailwind.config.js
module.exports = {
darkMode: 'class',
// ...
}
現在,有 dark:
開頭的這些類別會根據 <html>
標籤裡的class 是否有 dark
來做對應的變化,而不是根據原本的 色彩偏好方案
(prefers-color-scheme)。
<!-- 深色模式還沒開啟 -->
<html>
<body>
<!-- 所以背景還是白色 -->
<div class="bg-white dark:bg-black">
<!-- ... -->
</div>
</body>
</html>
<!-- 深色模式開啟了 -->
<html class="dark">
<body>
<!-- 背景就變成黑色了 -->
<div class="bg-white dark:bg-black">
<!-- ... -->
</div>
</body>
</html>
其實隨便看你要用什麼方法來幫 <html>
標籤增加 dark
這個 class,不過通常都是寫一點點簡單的 js ,然後從像是本地端之類的地方去讀取設定檔,然後再去更新 DOM 節點。
下面有一個簡單的範例,是教你怎麼做到 淺色模式
、深色模式
,和 根據作業系統的偏好設定
。
// 最好在頁面讀取或更換主題的時候增加一行到 `head`來避免 FOUC
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
// 當使用者選擇 淺色模式 時
localStorage.theme = 'light'
// 當使用者選擇 深色模式 時
localStorage.theme = 'dark'
// 當使用者選擇 根據作業系統偏好設定 時
localStorage.removeItem('theme')
同樣的,你可以根據自己的心情喜好去管理它 (就看你今天爽不爽這樣),甚至是你想要把每個使用者的偏好設定都存在你伺服器的資料庫,然後再讀出來設定頁面,都隨便你。
當 darkMode 參數設為 class
時, 深色模式功能的特性優先權會高於一般的功能,因為選擇器包含了一個額外的 class。這代表某些情況下,有的功能組合後的效果在 class
和 media
模式下會有些微的差異。
舉個例,先參考一下這個 HTML:
<div class="text-black text-opacity-50 dark:text-white">
<!-- ... -->
</div>
當 darkMode 參數設為 media
時,dark:text-white
就會和 text-black
一樣擁有 text-opacity-50
這個特性。因為在生成 CSS 時,text-opacity-50
定義的時間比 dark:text-white
晚,所以白色的文字才會擁有 50% 的透明度。
而當參數設為 class
時,dark:text-white
特性的優先權會 提高,所以即使把定義的時間提前一點,它也會把 text-opacity-50
的效果覆蓋掉並重設回 1 。所以如果使用的是 class
參數,你就必須用深色模式中重新指定一次透明度,以確保特性存在:
<div class="text-black text-opacity-50 dark:text-white dark:text-opacity-50">
<!-- ... -->
</div>