過度宣傳還是必要功能?瞭解深色模式的所有相關資訊,以及如何支援這項功能,讓使用者受益!
簡介
深色模式推出前的深色模式
深色模式已全面支援。 在個人電腦剛問世時,深色模式並非選項,而是事實:單色 CRT 電腦螢幕是透過在螢光幕上發射電子束運作,而早期 CRT 使用的螢光粉是綠色。由於文字以綠色顯示,其餘畫面則為黑色,因此這些機型通常稱為「綠色螢幕」。
隨後推出的彩色 CRT 透過使用紅色、綠色和藍色螢光粉,顯示多種顏色。他們同時啟動三種螢光粉,藉此產生白色。 隨著更精密的WYSIWYG 桌上排版技術問世,讓虛擬文件看起來像實體紙張的概念開始流行。
深色文字搭配白色背景的設計趨勢由此開始,並延續到早期的文件式網頁。第一個瀏覽器「WorldWideWeb」WorldWideWeb(請注意,當時甚至還沒有發明 CSS),就是以這種方式顯示網頁。趣味小知識:史上第二個瀏覽器「Line Mode Browser」是以終端機為基礎的瀏覽器,採用深色背景搭配綠色文字。如今,網頁和網路應用程式通常會以淺色背景搭配深色文字設計,這項基本假設也已硬式編碼至使用者代理程式樣式表,包括 Chrome。
CRT 時代早已結束。 內容消費和創作已轉移至行動裝置,這些裝置使用背光 LCD 或節能 AMOLED 螢幕。電腦、平板電腦和智慧型手機變得更小巧輕便,因此出現了新的使用模式。 網頁瀏覽、編寫程式碼娛樂和高階遊戲等休閒活動,通常會在下班後的光線昏暗環境中進行。甚至有人會在夜間躺在床上使用裝置。 越來越多人會在黑暗環境中使用裝置,因此深色模式的概念也越來越受歡迎。
深色模式的優點
基於美觀考量使用深色模式
當人們被問到為什麼喜歡或想要深色模式時,最常見的回答是「對眼睛比較友善」,其次是「優雅美觀」。Apple 在深色模式開發人員文件中明確指出:「對大多數使用者而言,啟用淺色或深色外觀是美觀上的選擇,可能與環境照明條件無關。」
深色模式做為無障礙工具
此外,也有人需要深色模式,並將其視為另一種無障礙工具,例如低視能使用者。我能找到最早的無障礙工具是 System 7 的「CloseView」功能,可切換「黑底白字」和「白底黑字」。雖然 System 7 支援色彩,但預設使用者介面仍為黑白。
一旦引入色彩,這些以反轉為基礎的實作方式就會顯現出缺點。 Szpiro 等人針對低視能人士如何存取運算裝置進行使用者研究,結果顯示所有受訪者都不喜歡反轉圖片,但許多人偏好在深色背景上顯示淺色文字。Apple 提供了「智慧反轉」功能,可反轉螢幕上的色彩,但圖片、媒體和使用深色樣式的應用程式除外,以滿足這類使用者的偏好。
電腦視覺症候群 (又稱數位眼部疲勞) 是低視力的一種特殊形式,定義為「與使用電腦 (包括桌上型電腦、筆電和平板電腦) 和其他電子螢幕 (例如智慧型手機和電子閱讀裝置) 相關的眼睛和視力問題」。有研究指出,青少年使用電子裝置 (尤其是在夜間) 會增加睡眠時長縮短、入睡時間延長和睡眠不足的風險。此外,許多報告指出,藍光會參與生理時鐘和睡眠週期的調節,而光線環境不規律可能會導致睡眠不足,進而影響情緒和工作表現 (根據 Rosenfield 的研究)。如要減少這些負面影響,可以透過 iOS 的「夜間模式」Night Shift或 Android 的「夜燈」Night Light等功能調整螢幕色溫,減少藍光。此外,使用深色主題或深色模式,避免明亮或不規則的光線,也有助於減輕負面影響。
深色模式可節省 AMOLED 螢幕的電力
最後,深色模式可大幅節省 AMOLED 螢幕的電力。AMOLEDAndroid 個案研究著重於 YouTube 等熱門 Google 應用程式,結果顯示省電幅度最高可達 60%。如要進一步瞭解這些案例研究和各應用程式的省電量,請觀看下方影片。
在作業系統中啟用深色模式
現在我們已瞭解深色模式對許多使用者來說為何如此重要,接下來就來看看如何支援深色模式。
支援深色模式或深色主題的作業系統,通常會在設定中提供啟用選項。在 macOS X 中,這個選項位於系統偏好設定的「一般」部分,稱為「外觀」 (螢幕截圖);在 Windows 10 中,這個選項位於「色彩」部分,稱為「選擇你的色彩」 (螢幕截圖)。在 Android Q 中,您可以在「顯示」下方找到「深色主題」切換開關 (螢幕截圖), 而在 iOS 13 中,您可以在設定的「螢幕顯示與亮度」部分變更「外觀」 (螢幕截圖)。
prefers-color-scheme 媒體查詢
開始之前,最後一個理論概念。
媒體查詢可讓作者測試及查詢使用者代理程式或顯示裝置的值或功能,與要算繪的文件無關。這些選取器用於 CSS @media 規則,可有條件地將樣式套用至文件,以及用於各種其他環境和語言,例如 HTML 和 JavaScript。媒體查詢第 5 級導入了所謂的使用者偏好媒體功能,也就是網站偵測使用者偏好內容顯示方式的方法。
prefers-color-scheme 媒體功能可用於偵測使用者是否要求網頁使用淺色或深色主題。支援的值如下:
light: 表示使用者已通知系統,偏好使用淺色主題的頁面 (淺色背景上的深色文字)。dark: 表示使用者已通知系統,偏好深色主題的網頁 (淺色文字搭配深色背景)。
支援深色模式
確認瀏覽器是否支援深色模式
由於系統會透過媒體查詢回報深色模式,因此只要檢查媒體查詢 prefers-color-scheme 是否相符,即可輕鬆確認目前的瀏覽器是否支援深色模式。請注意,我沒有納入任何值,只是單純檢查媒體查詢是否相符。
if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
console.log('🎉 Dark mode is supported');
}
撰寫本文時,Chrome 和 Edge 76 以上版本、Firefox 67 以上版本,以及 macOS 12.1 以上版本和 iOS 13 以上版本的 Safari,都支援 prefers-color-scheme (適用於桌機和行動裝置)。如為其他瀏覽器,請參閱「我可以使用支援表格嗎?」文件。
在要求時瞭解使用者的偏好設定
網站可透過 Sec-CH-Prefers-Color-Scheme 用戶端提示標頭,在要求時選擇性取得使用者的色彩配置偏好設定,讓伺服器內嵌正確的 CSS,避免出現錯誤的色彩主題。
練習時使用深色模式
最後,我們來看看實際支援深色模式的樣子。 就像 Highlander 一樣,深色模式只能擇一:深色或淺色,但絕不會同時存在!為什麼我要提到這點?因為這項事實應會影響載入策略。請勿強迫使用者在重要算繪路徑中下載 CSS,因為這會導致他們目前未使用的模式無法運作。為盡量提升載入速度,我將範例應用程式的 CSS 分成三部分,以延遲載入非重要 CSS,實際做法如下列建議所示:
style.css,其中包含網站上普遍使用的通用規則。dark.css,其中只包含深色模式所需的規則。light.css,其中只包含淺色模式所需的規則。
載入策略
後兩者 (light.css 和 dark.css) 會透過 <link media> 查詢有條件地載入。一開始並非所有瀏覽器都會支援 prefers-color-scheme (可使用上述模式偵測),
我會透過在極小的內嵌指令碼中,以條件式插入的 <link rel="stylesheet"> 元素載入預設 light.css 檔案,動態處理這個問題 (light 是任意選擇,我也可以將 dark 設為預設的回退體驗)。為避免未套用樣式的內容閃爍,我會隱藏網頁內容,直到 light.css 載入完成為止。
<script>
// If `prefers-color-scheme` is not supported, fall back to light mode.
// In this case, light.css will be downloaded with `highest` priority.
if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all') {
document.documentElement.style.display = 'none';
document.head.insertAdjacentHTML(
'beforeend',
'<link rel="stylesheet" href="/light.css" onload="document.documentElement.style.display = \'\'">',
);
}
</script>
<!--
Conditionally either load the light or the dark stylesheet. The matching file
will be downloaded with `highest`, the non-matching file with `lowest`
priority. If the browser doesn't support `prefers-color-scheme`, the media
query is unknown and the files are downloaded with `lowest` priority (but
above I already force `highest` priority for my default light experience).
-->
<link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)" />
<link
rel="stylesheet"
href="/light.css"
media="(prefers-color-scheme: light)"
/>
<!-- The main stylesheet -->
<link rel="stylesheet" href="/style.css" />
樣式表架構
我盡量使用 CSS 變數,這樣一來,我的通用 style.css 就能保持通用,所有淺色或深色模式的自訂作業都會在另外兩個檔案 dark.css 和 light.css 中進行。以下是實際樣式的摘錄內容,但應該足以傳達整體概念。
我宣告了兩個變數 --color 和 --background-color,這兩個變數基本上會建立淺色背景上的深色文字和深色背景上的淺色文字基準主題。
/* light.css: 👉 dark-on-light */
:root {
--color: rgb(5, 5, 5);
--background-color: rgb(250, 250, 250);
}
/* dark.css: 👉 light-on-dark */
:root {
--color: rgb(250, 250, 250);
--background-color: rgb(5, 5, 5);
}
在 style.css 中,我會在 body { … } 規則中使用這些變數。
由於它們是在 :root CSS 虛擬類別中定義,因此會向下層疊,這有助於我宣告全域 CSS 變數。CSS 虛擬類別是 HTML 中代表 <html> 元素的選取器,與 html 選取器相同,但特異性較高。
/* style.css */
:root {
color-scheme: light dark;
}
body {
color: var(--color);
background-color: var(--background-color);
}
在上述程式碼範例中,您可能已注意到具有以空格分隔值 light dark 的屬性 color-scheme。
這會告知瀏覽器應用程式支援的顏色主題,並允許瀏覽器啟用使用者代理程式樣式表的特殊變體,例如讓瀏覽器以深色背景和淺色文字算繪表單欄位、調整捲軸,或啟用主題感知醒目顯示顏色。color-scheme 的確切詳細資料請參閱 CSS 色彩調整模組第 1 級。
接下來,只要為網站上重要的項目定義 CSS 變數即可。使用深色模式時,以語意方式整理樣式有很大的幫助。舉例來說,請考慮呼叫變數 --accent-color,而不是 --highlight-yellow,因為「黃色」在深色模式中可能不是黃色,反之亦然。以下是範例中使用的其他變數。
/* dark.css */
:root {
--color: rgb(250, 250, 250);
--background-color: rgb(5, 5, 5);
--link-color: rgb(0, 188, 212);
--main-headline-color: rgb(233, 30, 99);
--accent-background-color: rgb(0, 188, 212);
--accent-color: rgb(5, 5, 5);
}
/* light.css */
:root {
--color: rgb(5, 5, 5);
--background-color: rgb(250, 250, 250);
--link-color: rgb(0, 0, 238);
--main-headline-color: rgb(0, 0, 192);
--accent-background-color: rgb(0, 0, 238);
--accent-color: rgb(250, 250, 250);
}
完整範例
在下列 Glitch 嵌入內容中,您可以看到完整範例,將上述概念付諸實踐。嘗試在特定作業系統的設定中切換深色模式,看看網頁的反應。
載入影響
試用這個範例時,您會發現我透過媒體查詢載入 dark.css 和 light.css 的原因。請嘗試切換深色模式並重新載入頁面:
系統仍會載入目前不相符的特定樣式表,但會將優先順序設為最低,
因此這些樣式表絕不會與網站目前需要的資源競爭。
prefers-color-scheme 的瀏覽器上,以預設淺色模式載入的網站會以最低優先順序載入深色模式 CSS。回應深色模式變更
與任何其他媒體查詢變更一樣,深色模式變更可透過 JavaScript 訂閱。
舉例來說,您可以使用這項功能動態變更網頁的網站小圖示,或是變更<meta name="theme-color">,藉此決定 Chrome 中網址列的顏色。如要查看主題顏色和網站小圖示的變化,請在另一個分頁中開啟示範,上述完整範例會顯示實際運作情形。
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
darkModeMediaQuery.addEventListener('change', (e) => {
const darkModeOn = e.matches;
console.log(`Dark mode is ${darkModeOn ? '🌒 on' : '☀️ off'}.`);
});
從 Chromium 93 和 Safari 15 開始,您可以根據媒體查詢,使用 meta 主題顏色元素的 media 屬性調整顏色。系統會選取第一個相符的項目。舉例來說,您可以為淺色模式設定一種顏色,為深色模式設定另一種顏色。撰寫本文時,您無法在資訊清單中定義這些項目。請參閱 w3c/manifest#975 GitHub 問題。
<meta
name="theme-color"
media="(prefers-color-scheme: light)"
content="white"
/>
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />
偵錯及測試深色模式
在開發人員工具中模擬 prefers-color-scheme
切換整個作業系統的色彩配置可能會很快就讓人感到厭煩,因此 Chrome 開發人員工具現在可讓您模擬使用者偏好的色彩配置,且只會影響目前顯示的分頁。開啟指令選單,開始輸入 Rendering,執行 Show Rendering 指令,然後變更「模擬 CSS 媒體功能 prefers-color-scheme」選項。

使用 Puppeteer 擷取 prefers-color-scheme 的螢幕截圖
Puppeteer 是 Node.js 程式庫,可透過開發人員工具通訊協定提供高階 API,用來控制 Chrome 或 Chromium。我們提供 dark-mode-screenshot Puppeteer 指令碼,可讓您在深色和淺色模式中建立網頁的螢幕截圖。您可以一次性執行這個指令碼,也可以將其納入持續整合 (CI) 測試套件。
npx dark-mode-screenshot --url https://googlechromelabs.github.io/dark-mode-toggle/demo/ --output screenshot --fullPage --pause 750
深色模式最佳做法
避免使用純白色
您可能已注意到,我並未使用純白色。為避免發光和溢色,我選擇稍微深一點的白色,例如 rgb(250, 250, 250) 就很適合。
重新著色並調暗相片圖像
比較下方的兩張螢幕截圖,您會發現不僅核心主題從深色文字搭配淺色背景變更為淺色文字搭配深色背景,連帶主頁橫幅也略有不同。我的使用者研究顯示,啟用深色模式時,大多數受訪者偏好色彩飽和度稍低、亮度稍暗的圖片。我將此稱為「重新著色」。
我可以使用圖片的 CSS 篩選器重新著色。
我使用的 CSS 選取器會比對所有網址中沒有 .svg 的圖片,
目的是要為向量圖形 (圖示) 提供與圖片 (相片) 不同的重新著色處理方式,詳情請見下一個段落。
請注意,我再次使用 CSS 變數,
以便日後彈性變更篩選器。
由於只有在深色模式 (即 dark.css 處於啟用狀態) 下才需要重新著色,因此 light.css 中沒有對應的規則。
/* dark.css */
--image-filter: grayscale(50%);
img:not([src*='.svg']) {
filter: var(--image-filter);
}
使用 JavaScript 自訂深色模式重新著色強度
每個人的需求不同,因此深色模式的設定也不盡相同。
只要採用上述重新著色方法,我就可以輕鬆將灰階強度設為使用者偏好設定,並透過 JavaScript 變更,而且只要設定 0% 值,就能完全停用重新著色功能。請注意,document.documentElement 會提供文件根元素的參照,也就是我可以使用 :root CSS 虛擬類別參照的相同元素。
const filter = 'grayscale(70%)';
document.documentElement.style.setProperty('--image-filter', value);
反轉向量圖形和圖示
對於向量繪圖 (在本例中,向量繪圖用做圖示,我透過 <img> 元素參照這些圖示),我使用不同的重新著色方法。研究顯示,使用者不喜歡相片反轉,但這項功能對大多數圖示來說效果極佳。我再次使用 CSS 變數,判斷一般和 :hover 狀態的反轉量。
請注意,我只反轉 dark.css 中的圖示,而非 light.css 中的圖示,且 :hover 在這兩種情況下會獲得不同的反轉強度,讓圖示根據使用者選取的模式,呈現略深或略淺的顏色。
/* dark.css */
--icon-filter: invert(100%);
--icon-filter_hover: invert(40%);
img[src*='.svg'] {
filter: var(--icon-filter);
}
/* light.css */
--icon-filter_hover: invert(60%);
/* style.css */
img[src*='.svg']:hover {
filter: var(--icon-filter_hover);
}
使用 currentColor 內嵌 SVG
如果是內嵌 SVG 圖片,您可以運用 currentColor CSS 關鍵字,代表元素 color 屬性的值,而不使用反轉篩選器。這樣就能在預設不會收到 color 值的屬性上使用該值。方便的是,如果 currentColor 用做 SVG fill 或 stroke 屬性的值,則會改為從顏色屬性的繼承值取得值。更棒的是,這也適用於 <svg><use href="…"></svg>,因此您可以擁有個別資源,而 currentColor 仍會套用至相關內容。請注意,這項功能僅適用於內嵌或 <use href="…"> SVG,
但不適用於以圖片形式參照的 SVG,或透過 CSS 參照的 SVG。
src請參閱下方的示範。
<!-- Some inline SVG -->
<svg xmlns="http://www.w3.org/2000/svg"
stroke="currentColor"
>
[…]
</svg>
模式之間的轉換更流暢
由於 color 和 background-color 都是可動畫化的 CSS 屬性,因此從深色模式切換到淺色模式,或反過來切換時,可以順暢地完成。建立動畫非常簡單,只要為這兩個屬性宣告兩個 transition 即可。
下方範例說明整體概念,您可以在試用版中實際體驗。
body {
--duration: 0.5s;
--timing: ease;
color: var(--color);
background-color: var(--background-color);
transition: color var(--duration) var(--timing), background-color var(
--duration
) var(--timing);
}
深色模式的美術指導
一般而言,基於載入效能考量,我建議只使用 <link> 元素的 media 屬性中的 prefers-color-scheme
,而不是樣式表中的內嵌 prefers-color-scheme。不過,在某些情況下,您可能確實想直接在 HTML 程式碼中內嵌 prefers-color-scheme。
藝術指導就是這樣的情況。
在網路上,美術指導負責處理網頁的整體視覺外觀,以及如何以視覺方式傳達訊息、激發情緒、對比特色,並在心理上吸引目標對象。
在深色模式下,設計師可自行判斷特定模式的最佳圖片,以及圖片重新著色是否不夠好。如果與 <picture> 元素搭配使用,要顯示的圖片 <source> 可以取決於 media 屬性。
在下方範例中,我顯示深色模式的西半球,以及淺色模式或未指定偏好設定時的東半球,在所有其他情況下則預設為東半球。當然,這純粹是為了說明。
在裝置上切換深色模式,即可查看差異。
<picture>
<source srcset="western.webp" media="(prefers-color-scheme: dark)" />
<source srcset="eastern.webp" media="(prefers-color-scheme: light)" />
<img src="eastern.webp" />
</picture>
深色模式,但新增停用選項
如上述「深色模式的優點」一節所述,大多數使用者會選擇深色模式,是為了追求美觀。因此,部分使用者可能喜歡使用深色作業系統 UI,但仍偏好以習慣的方式查看網頁。建議您一開始先遵守瀏覽器透過 prefers-color-scheme 傳送的信號,然後視需要允許使用者覆寫系統層級設定。
<dark-mode-toggle> 自訂元素
您當然可以自行建立這段程式碼,但也可以直接使用我為此目的建立的現成自訂元素 (網頁元件)。這個外掛程式稱為 <dark-mode-toggle>,可將切換鈕 (深色模式:開啟/關閉) 或主題切換器 (主題:淺色/深色) 新增至網頁,並提供完整自訂功能。下方範例顯示實際運作的元素 (喔,我還在其他
範例
中偷偷加入這個元素)。
<dark-mode-toggle
legend="Theme Switcher"
appearance="switch"
dark="Dark"
light="Light"
remember="Remember this"
></dark-mode-toggle>
<dark-mode-toggle> 淺色模式。
<dark-mode-toggle> 深色模式。
請在下列示範中,點按或輕觸右上角的深色模式控制項。 如果您勾選第三和第四個控制項中的核取方塊,即使重新載入頁面,系統也會記住您選取的模式。這樣一來,訪客就能在深色模式下瀏覽網站, 或是在淺色模式下瀏覽網站,反之亦然。
結論
支援深色模式很有趣,而且能開創新的設計方向。
對部分訪客來說,這可能是無法使用網站和成為滿意使用者之間的差異。雖然有幾項需要注意的陷阱,而且務必進行仔細測試,但深色模式絕對是展現您重視所有使用者的絕佳機會。本文提及的最佳做法和 <dark-mode-toggle> 自訂元素等輔助工具,應能協助您打造出色的深色模式體驗。歡迎在 Twitter 上告訴我你的創作內容,以及這篇文章是否實用,或是有任何改進建議。感謝閱讀!🌒
相關連結
prefers-color-scheme 媒體查詢的相關資源:
color-scheme 中繼標記和 CSS 屬性相關資源:
color-schemeCSS 屬性和中繼標記- Chrome 平台狀態頁面
- Chromium 錯誤
- CSS 顏色調整模組第 1 級規格
- CSS WG GitHub Issue for the meta tag and the CSS property
- HTML WHATWG GitHub Issue for the meta tag
深色模式一般連結:
這則貼文的背景研究文章:
特別銘謝
prefers-color-scheme 媒體功能、color-scheme CSS 屬性和相關中繼標記的實作工作,是由 👏 Rune Lillesveen 完成。
Rune 也是 CSS 顏色調整模組第 1 級規格的共同編輯者。
我要 🙏 感謝 Lukasz Zbylut、
Rowan Merewood、
Chirag Desai 和
Rob Dodson
對本文的詳盡審查。
載入策略是 Jake Archibald 的創意發想。
Emilio Cobos Álvarez 向我說明瞭正確的prefers-color-scheme偵測方法。
這則提示附有參照的 SVG 和 currentColor,是由 Timothy Hatcher 提供。最後,我要感謝參與各項使用者研究的眾多匿名人士,他們協助我們制定了本文中的建議。