使用者偏好設定媒體功能用戶端提示標頭

一組用戶端提示標頭可讓網站在要求時選擇性地取得使用者的媒體偏好設定,讓伺服器基於效能考量,內嵌正確的 CSS。

CSS 媒體查詢,尤其是 使用者偏好媒體功能 (例如 prefers-color-schemeprefers-reduced-motion),可能會對網頁需要傳送的 CSS 數量,以及使用者在網頁載入時的體驗,造成重大影響

著重於 prefers-color-scheme (但特別強調此原因也適用於其他使用者偏好媒體功能),最佳做法是不要在重要轉譯路徑中載入特定不相符的色彩配置的 CSS,改為一開始只載入目前相關的 CSS。其中一種方法是透過 <link media>

不過,如果是人氣很高的網站 (例如 Google 搜尋),為了因應使用者偏好的媒體功能 (例如 prefers-color-scheme),並基於效能考量而內嵌 CSS,最好在要求時就知道偏好的色彩配置 (或其他使用者偏好的媒體功能),這樣一來,初始 HTML 酬載就會內嵌正確的 CSS。

此外,特別針對 prefers-color-scheme,網站應盡可能避免閃爍不準確的色彩主題

Sec-CH-Prefers-Color-SchemeSec-CH-Prefers-Reduced-Motion 用戶端提示標頭是一系列用戶偏好媒體功能用戶端提示標頭中的第一個,旨在解決這個問題。

用戶端提示的背景資訊

HTTP 用戶端提示會定義 Accept-CH 回應標頭,讓伺服器用來通告自身對於主動式內容交涉的使用要求標頭 (通常稱為用戶端提示)。使用者偏好媒體功能用戶端提示標頭提案定義了一組用戶端提示,用來傳達使用者偏好的媒體功能。這些用戶端提示會以所回報的對應使用者偏好設定媒體功能命名。例如,系統會根據 prefers-color-scheme 目前偏好的色彩配置透過適當命名的 Sec-CH-Prefers-Color-Scheme 用戶端提示回報。

重要用戶端提示的背景資訊

使用者偏好媒體功能用戶端提示標頭中提出的用戶端提示,最常用於重要用戶端提示。重要用戶端提示是用戶端提示,可有效變更產生的資源。這類資源應在各次網頁載入 (包括初始網頁載入) 中一致擷取,以免使用者看到不自然的切換畫面。

用戶端提示語法

使用者偏好設定媒體功能包含名稱 (例如 prefers-reduced-motion) 和允許的值 (例如 no-preferencereduce)。每個用戶端提示標頭欄位都會以 HTTP 的結構化標頭物件表示,其中包含一個項目,其值為 字串。舉例來說,如要傳達使用者偏好深色主題和減少動態效果,用戶端提示會如以下範例所示。

GET / HTTP/2
Host: example.com
Sec-CH-Prefers-Color-Scheme: "dark"
Sec-CH-Prefers-Reduced-Motion: "reduce"

上述用戶端提示中傳達的資訊,其 CSS 等價分別為 @media (prefers-color-scheme: dark) {}@media (prefers-reduced-motion: reduce) {}

完整的用戶端提示清單

用戶端提示清單的設計方式,是參考媒體查詢第 5 級使用者偏好媒體功能

用戶端提示 接受的值 對應的使用者偏好設定媒體功能
Sec-CH-Prefers-Reduced-Motion no-preferencereduce prefers-reduced-motion
Sec-CH-Prefers-Reduced-Transparency no-preferencereduce prefers-reduced-transparency
Sec-CH-Prefers-Contrast no-preferencelessmorecustom prefers-contrast
Sec-CH-Forced-Colors activenone forced-colors
Sec-CH-Prefers-Color-Scheme lightdark prefers-color-scheme
Sec-CH-Prefers-Reduced-Data no-preferencereduce prefers-reduced-data

瀏覽器支援

Chromium 93 支援 Sec-CH-Prefers-Color-Scheme 用戶端提示標頭。Chromium 108 支援 Sec-CH-Prefers-Reduced-Motion 用戶端提示標頭。其他供應商的意見回饋 (即 WebKitMozilla) 仍在處理中。

Sec-CH-Prefers-Color-Scheme」示範

請試試 Chromium 93 中的示範,並注意內嵌 CSS 如何根據使用者偏好的色彩配置變更。

Sec-CH-Prefers-Color-Scheme: dark

Sec-CH-Prefers-Color-Scheme: light

Sec-CH-Prefers-Reduced-Motion 的示範

請試試 Chromium 108 中的示範,並注意內嵌 CSS 如何根據使用者的動畫偏好設定而變更。

運作方式

  1. 用戶端向伺服器發出初始要求。 bash GET / HTTP/2 Host: example.com
  2. 伺服器會回應,透過 Accept-CH 告知用戶端其接受 Sec-CH-Prefers-Color-SchemeSec-CH-Prefers-Contrast 用戶端提示,而如同 Critical-CH 所述,該伺服器將 Sec-CH-Prefers-Color-Scheme 視為重大用戶端提示,其回應也會隨著 Vary 傳輸的回應變動。bash HTTP/2 200 OK Content-Type: text/html Accept-CH: Sec-CH-Prefers-Color-Scheme, Sec-CH-Prefers-Contrast Vary: Sec-CH-Prefers-Color-Scheme Critical-CH: Sec-CH-Prefers-Color-Scheme
  3. 接著,用戶端會透過 Sec-CH-Prefers-Color-Scheme 重試要求,讓伺服器瞭解採用深色配置內容的使用者偏好。bash GET / HTTP/2 Host: example.com Sec-CH-Prefers-Color-Scheme: "dark"
  4. 這樣一來,伺服器就能根據用戶端偏好設定調整回應,例如將負責深色主題的 CSS 內嵌至回應主體。

Node.js 範例

以下 Node.js 範例是為熱門的 Express.js 架構編寫,說明如何在實際操作中處理 Sec-CH-Prefers-Color-Scheme 用戶端提示標頭。這段程式碼實際上是上述示範的動力來源。

app.get("/", (req, res) => {
  // Tell the client the server accepts the `Sec-CH-Prefers-Color-Scheme` client hint…
  res.set("Accept-CH", "Sec-CH-Prefers-Color-Scheme");
  // …and that the server's response will vary based on its value…
  res.set("Vary", "Sec-CH-Prefers-Color-Scheme");
  // …and that the server considers this client hint a _critical_ client hint.
  res.set("Critical-CH", "Sec-CH-Prefers-Color-Scheme");
  // Read the user's preferred color scheme from the headers…
  const prefersColorScheme = req.get("sec-ch-prefers-color-scheme");
  // …and send the adequate HTML response with the right CSS inlined.
  res.send(getHTML(prefersColorScheme));
});

隱私權和安全性考量

Chromium 團隊根據「控制強大網路平台功能的存取權」一文中定義的核心原則,設計並實作使用者偏好設定媒體功能的用戶端提示標頭,包括使用者控制、資訊公開和人體工學。

HTTP 用戶端提示的安全性考量和用戶端提示的安全性考量同樣適用於本提案。

參考資料

特別銘謝

感謝 Yoav Weiss 提供寶貴意見和建議。主頁橫幅圖片由 Tdadamemd 提供,取自 Wikimedia Commons