Introduction
Dark mode 是近兩年來蠻熱門的議題, 講白了, 它就是一種 theme, 一種依照當前環境做區分的 theme, 更是一種讓服務貼近生活的態度.
如果你的服務不支援 dark mode 會怎樣 ?
老實說一點都不會怎樣, 只是…在特定的環境下, 會讓 user 在使用上會感到吃力且疲倦, 試想 facebook 好了, 它的基調大多是白色背景單配黑色的文字, 在燈光明亮的狀態下瀏覽或許感到舒適, 但是, 如果在昏暗亦或是睡前躺在床上使用時, 眼睛便會因為對比的銳利而感到疲憊, 我想…這都不是我們想提供給 user 的感受.
所以, 除了 OS 提供 dark mode 的功能外, 服務所呈現的 web content 是否也能提供 dark mode 呢 ? 這便是我們今天想要討論的議題.
最新的 macOS 在 System Preference 裏提供了 light / dark mode 供 user 選擇, 大部分的 UI 也會依照 user 的選擇做出相對應的變化, 除此之外, 很多應用程式, 比方說 Chrome, 亦提供了 dark mode 這樣的 theme 讓 user 有更多的選擇, 顯示說 dark mode 不僅僅是一種潮流, 更是一個良好的產品態度的彰顯.
在 WWDC 2019 便有一環講到如何讓 web content support dark mode (iOS 13). 而且 Android Q 亦有 support dark theme.
- Support Dark mode in Your Web Content
- Android Q with Dark theme
Nothing but CSS
如同上段所述, dark mode 就是一種 theme, 也就是說先決條件必須要有一套完整的 design language, 一但有了明確且完整的 design language 後, 剩下的事情就相對簡單許多.
如下所示, 這是筆者拿來示範用的 demo site (light mode).
我們的目標很明確, 即設計一 CSS dark mode 的 theme, 讓 web page 可以自動的依據當前系統設定, 自動將 web content 轉換成 dark mode
在 CSS 的設定上, 其實非常的簡單, 只要明確在 root 定義 color-scheme, 其實便已完成了
<style>:root {
color-scheme: light dark;
}</style>
透過該屬性的設置, 便可以快速的設定當前 web page 的 color scheme, 主色系便會自動被 apply, 比方說 background color 和 text color
方便歸方便, 不過很多時候系統預設的 color scheme 可能與服務的 design language 不盡相同, 因此更細緻化的呈現是有必要的. 那麼…除了 color-scheme 的設置外, 我們還能有什麼樣的手段呢 ?
可以透過 CSS media query 的條件設置, 來 overwrite 一些相關屬性, 其運作原理很簡單, 只要當前的 OS 設置為 dark mode, 便會掉進去我們預期的設定
<style>header {
background-color: #fff;
color: #000;
}@media (prefers-color-scheme: dark) {
header {
background-color: #000;
color: #fff;
}
}</style>
如此, developers 便可以根據不同的 module 做出更為細緻且出色的表現, 如果搭配 CSS var() 的使用, 更可以讓這些 color scheme 更好管理且套用.
讓我們把上述的 CSS 再改寫一下
<style>:root {
--header-background-color: #fff;
--header-text-color: #000;
}header {
background-color: var(--header-background-color);
color: var(--header-text-color);
}@media (prefers-color-scheme: dark) {
:root {
--header-background-color: #000;
--header-text-color: #fff;
}
}</style>
瞧出箇中翹楚了嗎 ? 透過 CSS, 便能輕輕鬆鬆讓你的服務也能 support dark mode. 讓我們看看在 macOS 以及 iOS 13 上面的表現
What else ?
WWDC 2019 除了有揭露 dark mode 於 CSS 的設置方法外, 另外還有其他設置方法, 基本上只要有 support media query 語法的 html tag, 應該都可以吃得到 OS dark mode 模式.
<picture>
<source srcset="mojave-night.jpg"media="prefers-color-scheme: dark">
<img src="mojave-day.jpg">
</picture>
如上所示, developer 便可以根據當前 OS 設置來做不同的 image 呈現, 讓 dark mode 的整體支援更加完善.
看了以上介紹, 如果對 dark mode 有興趣的朋友, 只要你的 macOS 為 Mojave & safari version 12.1.1 以上, 便可以依照上述步驟來感受 dark mode 帶來的全新感受.
Appearance tracking
完成 dark mode 的設置後,追蹤 user 的使用情況亦是 frontend 需要特別注意的一個重要環節,由於 server side 無法取得當前 OS 的 appearance status,這表示說 i13n 的追蹤還是得由 client 來進行發動。
一般的頁面可以透過上段所提到的 <picture /> 再搭配 1pixel image 的方式來進行 beacon fire。
<picture>
<source srcset="beacon?appearance=dark" media="prefers-color-scheme: dark">
<img src="beacon?appearance=light">
</picture>
如此便可以快速的取得 appearance usage
不過在 AMP 類型的 web page,這樣的設置法會有錯誤,這是因為 AMP 下 <img /> 是不 allow 的 (需用 <amp-img /> 替代),所以如果想要在 AMP 下追蹤使用情況的話,就必須要額外加工,作法基本上和 <picture /> 大同小異
<style>:root {
--al: block;
--ad: none;
}[class|="appearance"] {
position: fixed;
left: 0;
top: 0;
width: 1px;
height: 0px;
display: none;
}.appearance-tracker-light {
display: var(--al);
}.appearance-tracker-dark {
display: var(--ad);
}@media (prefers-color-scheme: dark) {
:root {
--al: none;
--ad: block;
}
}
</style><div class="appearance-tracker-dark">
<amp-img src="beacon?appearance=dark" width="1" height="1"></amp-img>
</div><div class="appearance-tracker-light">
<amp-img src="beacon?appearance=light" width="1" height="1"></amp-img>
</div>
如上所示,透過 AMP runtime 的特性 (in viewport 且 display 不為 none 才會發動 image fetch) 再加上 CSS prefers-color-scheme: dark 的變數配置,隨著 OS appearance 的差異讓相對應得 <amp-img /> 動態呈現在 viewport 中,彈指之間便可以完成 AMP appearance beacon 發送,目前 Yahoo!奇摩拍賣 首頁便是利用這樣的方式來進行 data collection。
有興趣的朋友如果有這類需求的話,不妨嘗試看看。
Detect Dark mode with JavaScript
除了上述的方法外,其實也可以透過一個古老的 Web API — matchMedia 來偵測當前環境是否有支援 dark mode。
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
// dark mode
}
有兩上述兩種方式,相信對於 developer 來說可以更多元的來決定以及應用 dark mode。