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

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

CSS 媒體查詢,特別是 prefers-color-schemeprefers-reduced-motion使用者偏好媒體功能,可能會對需要由網頁提供的 CSS 數量以及使用者載入網頁時體驗的 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 用戶端提示回報。

重要客戶提示背景資訊

使用者偏好設定媒體功能用戶端提示標頭中提出的用戶端提示,大概是重要用戶端提示。「重要用戶端提示」是「用戶端提示」,可以大幅改變產生的資源。這類資源應在各網頁載入時 (包括「初始」initial頁面載入) 一致擷取,以免造成使用者看不到的切換按鈕。

用戶端提示語法

使用者偏好設定媒體功能包含名稱 (例如 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:深色

Sec-CH-Prefers-Color-Scheme:淺色

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 提供的寶貴意見和建議。TdadamemdWikimedia Commons 上提供的主頁橫幅。