使用色彩配置 CSS 屬性和對應的中繼標記改善深色模式預設樣式

color-scheme CSS 屬性和相應的中繼標記可讓開發人員選擇網頁採用使用者代理程式樣式表的特定主題預設值。

prefers-color-scheme 使用者偏好設定媒體功能可讓開發人員完全掌控網頁外觀。如果您不熟悉深色模式,請參閱我的文章「prefers-color-scheme: Hello darkness, my old friend」,其中記錄了我對打造出色的深色模式體驗所知的一切。

本文中只有簡短提到的一個謎題,就是 color-scheme CSS 屬性及同名的對應中繼標記。這兩種方法都能讓您在開發人員的作業中更輕鬆,因為您可以選擇將頁面納入使用者代理程式樣式表的特定主題預設值,例如表單控制項、捲軸列以及 CSS 系統顏色。同時,這項功能可以防止瀏覽器自行套用任何轉換。

瀏覽器支援

prefers-color-scheme

瀏覽器支援

  • Chrome:76。
  • Edge:79。
  • Firefox:67。
  • Safari:12.1 版。

資料來源

color-scheme

瀏覽器支援

  • Chrome:81。
  • Edge:81。
  • Firefox:96。
  • Safari:13。

資料來源

使用者代理程式樣式表

在繼續之前,讓我簡單說明什麼是使用者代理程式樣式表單。在大多數情況下,您可以將「使用者代理程式」(UA) 視為「瀏覽器」(browser) 的華麗說法。通用 Analytics 樣式表會決定網頁的預設外觀和感受。如其名所示,UA 樣式表會依據相關的使用者代理程式而定。您可以查看 Chrome (和 Chromium) 的 UA 樣式表,並與 FirefoxSafari (和 WebKit) 的樣式表進行比較。一般而言,通用 Analytics 樣式表對大部分的事項達成共識。舉例來說,這些屬性都會讓連結變成藍色、一般文字黑色和背景顏色白色,但也有重要的差異 (例如樣式表單控制項的樣式),但有時也很惱人。

進一步瞭解 WebKit 的 UA 樣式表,以及這項功能在深色模式中的運作方式。(在樣式表中執行「dark」的全文搜尋)。樣式表的預設預設會視深色模式開啟與關閉狀態而不同。為說明這一點,以下是使用 :matches 虛擬類別和 WebKit-internal 變數 (例如 -apple-system-control-background) 以及 WebKit-internal 預先處理器指令 #if defined 的 CSS 規則:

input,
input:matches([type="password"], [type="search"]) {
  -webkit-appearance: textfield;
  #if defined(HAVE_OS_DARK_MODE_SUPPORT) &&
      HAVE_OS_DARK_MODE_SUPPORT
    color: text;
    background-color: -apple-system-control-background;
  #else
    background-color: white;
  #endif
  /* snip */
}

您會發現上述 colorbackground-color 屬性有部分非標準值。text-apple-system-control-background 都不是有效的 CSS 顏色。這些是 WebKit 內部的語意顏色。

事實上,CSS 已將語意系統顏色標準化。這些值已在 CSS 顏色模組第 4 級中指定。舉例來說,Canvas (請勿與 <canvas> 標記混淆) 是用於應用程式內容或文件的背景,而 CanvasText 則是用於應用程式內容或文件中的文字。這兩者是相輔相成,不應單獨使用。

UA 樣式表可以使用專屬或標準化語意系統顏色,決定 HTML 元素的預設顯示方式。如果作業系統設為深色模式或使用深色主題,CanvasText (或 text) 會依條件設為白色,Canvas (或 -apple-system-control-background) 則會設為黑色。接著,通用 Analytics 樣式表只會指派下列 CSS 一次,且涵蓋淺色和深色模式。

/**
  Not actual UA stylesheet code.
  For illustrative purposes only.
*/
body {
  color: CanvasText;
  background-color: Canvas
}

color-scheme CSS 屬性

CSS 色彩調整模組第 1 級規格引進了模型,並控制使用者代理程式自動調整色彩的情形,目的是處理使用者偏好設定,例如深色模式、對比調整或特定所需色彩配置。

其中定義的 color-scheme 屬性可讓元素指出適合轉譯的配色方案。系統會根據使用者的偏好設定協調這些值,並選擇色彩配置,進而影響使用者介面 (UI) 的元素,例如表單控制項和捲軸列的預設顏色,以及 CSS 系統顏色的使用值。目前所支援的值如下:

  • normal 表示元素完全不瞭解配色方案,因此應使用瀏覽器的預設配色方案算繪元素。

  • [ light | dark ]+ 表示元素已知曉並可處理所列的色彩配置,並表示這些色彩配置之間的偏好順序。

在此清單中,light 代表淺色色彩配置,具有淺色背景顏色和深色前景顏色,dark 則代表淺色的色彩配置,以深色背景顏色和淺色前景顏色表示。

對於所有元素,使用色彩配置進行轉譯時,所有瀏覽器提供的 UI 元素所使用的顏色應與色彩配置的意圖相符。例如捲軸、拼字檢查底線、表單控制項等。

:root 元素上,使用色彩配置進行轉譯時,必須影響畫布的表面顏色 (也就是全域背景顏色)、color 屬性的初始值,以及系統顏色的使用值,並且應影響檢視區的捲動條。

/*
  The page supports both dark and light color schemes,
  and the page author prefers dark.
*/
:root {
  color-scheme: dark light;
}

color-scheme 中繼標記

如要遵循 color-scheme CSS 屬性,必須先下載 CSS (如果是透過 <link rel="stylesheet"> 參照) 並進行剖析。為協助使用者代理程式立即以所需色彩配置算繪網頁背景,您也可以在 <meta name="color-scheme"> 元素中提供 color-scheme 值。

<!--
  The page supports both dark and light color schemes,
  and the page author prefers dark.
-->
<meta name="color-scheme" content="dark light">

結合 color-schemeprefers-color-scheme

由於中繼標記和 CSS 屬性 (如果套用至 :root 元素) 最終會導致相同行為,因此我一律建議透過中繼標記指定色彩配置,讓瀏覽器更快採用偏好的配置。

雖然絕對基準網頁不需要額外的 CSS 規則,但一般來說,您應該一律將 color-schemeprefers-color-scheme 結合使用。舉例來說,WebKit 和 Chrome 用於經典連結藍色 rgb(0,0,238) 的專屬 WebKit CSS 顏色 -webkit-link,黑色背景上的對比度不足 2.23:1,且不符合 WCAG AA 和 WCAG AAA 規定

我已開啟 ChromeWebKitFirefox 的錯誤及 HTML 標準中的中繼問題,以便進行修正。

prefers-color-scheme 互動

color-scheme CSS 屬性和對應的 Meta 標記與 prefers-color-scheme 使用者偏好設定媒體功能的互動關係,一開始可能會讓人感到困惑。事實上,兩者搭配得非常好。最重要的是,color-scheme 專門用於決定預設外觀,而 prefers-color-scheme 則用於決定可設定樣式的外觀。為了讓這項概念更清楚,請假設下列網頁:

<head>
  <meta name="color-scheme" content="dark light">
  <style>
    fieldset {
      background-color: gainsboro;
    }
    @media (prefers-color-scheme: dark) {
      fieldset {
        background-color: darkslategray;
      }
    }
  </style>
</head>
<body>
  <p>
    Lorem ipsum dolor sit amet, legere ancillae ne vis.
  </p>
  <form>
    <fieldset>
      <legend>Lorem ipsum</legend>
      <button type="button">Lorem ipsum</button>
    </fieldset>
  </form>
</body>

網頁上的內嵌 CSS 程式碼會在一般情況下將 <fieldset> 元素的 background-color 設為 gainsboro,如果使用者偏好 prefers-color-scheme 使用者偏好媒體功能的 dark 配色方案,則會將 background-color 設為 darkslategray

透過 <meta name="color-scheme" content="dark light"> 元素,網頁會告知瀏覽器,它支援深色和淺色主題,並偏好深色主題。

視作業系統是否設為深色或淺色模式而定,整個網頁會根據使用者代理程式樣式表顯示深色或淺色,反之亦然。沒有其他開發人員提供的 CSS,用於變更段落文字或頁面背景顏色。

請注意,<fieldset> 元素的 background-color 會根據是否啟用深色模式而變更,並遵循開發人員在頁面上提供的內嵌樣式表單中的規則。可以是 gainsborodarkslategray

淺色模式的頁面。
淺色模式:開發人員和使用者代理程式指定的樣式。 文字為黑色,並根據使用者代理程式樣式表,顯示白色。 <fieldset> 元素的 background-colorgainsboro,如同內嵌的開發人員樣式表所示。
以深色模式顯示的網頁。
深色模式:開發人員和使用者代理程式指定的樣式。 文字為白色,背景則根據使用者代理程式樣式表為黑色。根據內嵌的開發人員樣式表,<fieldset> 元素的 background-colordarkslategray

<button> 元素的外觀由使用者代理程式樣式表控制。其 color 設為 ButtonText 系統顏色,而其 background-color 和四個 border-color 則設為系統顏色 ButtonFace

使用 ButtonFace 屬性的淺色模式頁面。
淺色模式:background-color 和各種 border-color 會設為 ButtonFace 系統顏色。

請注意 <button> 元素的 border-color 如何變化。border-top-colorborder-bottom-color計算值會從 rgba(0, 0, 0, 0.847) (偏黑) 切換為 rgba(255, 255, 255, 0.847) (偏白),因為使用者代理程式會根據色彩配置動態更新 ButtonFace。同樣適用於 <button> 元素的 color,該元素已設為對應的系統顏色 ButtonText

顯示計算出的顏色值與 ButtonFace 相符。
淺色模式:使用者代理程式樣式表中,border-top-colorborder-bottom-color 的計算值現在為 rgba(0, 0, 0, 0.847)ButtonFace
顯示在深色模式下,計算的顏色值仍與 ButtonFace 相符。
深色模式:在使用者代理程式樣式表中,同時設為 ButtonFaceborder-top-colorborder-bottom-color 計算值現在已 rgba(255, 255, 255, 0.847)

示範

您可以在 Glitch 上的示範中,查看 color-scheme 套用至大量 HTML 元素的效果。示範內容故意顯示 WCAG AA 和 WCAG AAA 違規,並使用上述警告中提及的連結顏色。

在淺色模式下進行的展示。
示範切換為 color-scheme: light
使用深色模式時的示範。
示範切換為 color-scheme: dark。請注意,連結顏色違反 WCAG AA 和 WCAG AAA 的規定

特別銘謝

color-scheme CSS 屬性和對應的 Meta 標記是由 Rune Lillesveen 實作。Rune 也是 CSS 色彩調整模組層級 1 規格的共同編輯工具。主頁橫幅由 Philippe Leone 提供,位於 Unsplash 網站上。