通过一组客户端提示标头,网站可以选择在请求时获取用户的媒体偏好设置,以便服务器出于性能方面的原因内嵌正确的 CSS。
CSS 媒体查询,尤其是 prefers-color-scheme
或 prefers-reduced-motion
等用户偏好媒体功能,可能会对网页需要传送的 CSS 量以及用户在网页加载时获得的体验产生重大影响。
重点介绍 prefers-color-scheme
,但强调该推理也适用于其他用户偏好设置媒体功能。最佳实践是,不要在关键渲染路径中加载特定不匹配配色方案的 CSS,而是在开始时仅加载当前相关的 CSS。一种方法是通过 <link media>
进行。
不过,如果Google 搜索等高流量网站希望遵循用户偏好媒体功能(例如 prefers-color-scheme
)并出于性能原因内嵌 CSS,则最好在请求时了解首选配色方案(或其他用户偏好媒体功能),以便初始 HTML 载荷中已内嵌正确的 CSS。
此外,对于 prefers-color-scheme
,网站会尽量避免闪烁不准确的配色主题。
Sec-CH-Prefers-Color-Scheme
和 Sec-CH-Prefers-Reduced-Motion
客户端提示标头是旨在解决此问题的一系列用户偏好媒体功能客户端提示标头中的第一个。
客户端提示背景知识
HTTP 客户端提示定义了 Accept-CH
响应标头,服务器可以使用该标头表明其使用请求标头进行主动内容协商(通常称为客户端提示)。用户偏好媒体功能客户端提示标头提案定义了一组旨在传达用户偏好媒体功能的客户端提示。这些客户端提示的命名方式与其报告的对应用户偏好媒体功能相同。例如,系统会通过恰当命名的 Sec-CH-Prefers-Color-Scheme
客户端提示报告当前根据 prefers-color-scheme
的首选配色方案。
关键客户端提示背景信息
用户偏好媒体功能客户端提示标头中提出的客户端提示可能最常用作重要客户端提示。关键客户端提示是指会对生成的资源产生实质性更改的客户端提示。在每次网页加载(包括初始网页加载)时,都应一致提取此类资源,以避免用户看到突兀的切换。
客户端提示语法
用户偏好媒体功能由名称(例如 prefers-reduced-motion
)和允许的值(例如 no-preference
或 reduce
)组成。每个客户端提示标头字段都表示为包含一个值为字符串的项的 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) {}
。
客户端提示的完整列表
客户端提示列表以 Media Queries Level 5 中的用户偏好媒体功能为蓝本。
客户端提示 | 允许的值 | 对应的用户偏好设置媒体功能 |
---|---|---|
Sec-CH-Prefers-Reduced-Motion |
no-preference 、reduce |
prefers-reduced-motion |
Sec-CH-Prefers-Reduced-Transparency |
no-preference 、reduce |
prefers-reduced-transparency |
Sec-CH-Prefers-Contrast |
no-preference 、less 、more 、custom |
prefers-contrast |
Sec-CH-Forced-Colors |
active 、none |
forced-colors |
Sec-CH-Prefers-Color-Scheme |
light 、dark |
prefers-color-scheme |
Sec-CH-Prefers-Reduced-Data |
no-preference 、reduce |
prefers-reduced-data |
浏览器支持
Chromium 93 支持 Sec-CH-Prefers-Color-Scheme
客户端提示标头。
Chromium 108 支持 Sec-CH-Prefers-Reduced-Motion
客户端提示标头。其他供应商(即 WebKit 和 Mozilla)的反馈仍待处理。
Sec-CH-Prefers-Color-Scheme
演示
在 Chromium 93 中试用演示版,并注意内嵌 CSS 如何根据用户的首选配色方案而发生变化。
Sec-CH-Prefers-Reduced-Motion
演示
在 Chromium 108 中试用演示版,并注意内嵌 CSS 如何根据用户的动作偏好设置而变化。
运作方式
- 客户端向服务器发出初始请求。
bash GET / HTTP/2 Host: example.com
- 服务器会响应,通过
Accept-CH
告知客户端它接受Sec-CH-Prefers-Color-Scheme
和Sec-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
- 然后,客户端会重试请求,通过
Sec-CH-Prefers-Color-Scheme
告知服务器其用户偏好使用深色主题的内容。bash GET / HTTP/2 Host: example.com Sec-CH-Prefers-Color-Scheme: "dark"
- 然后,服务器可以根据客户端的偏好设置量身定制响应,例如,将负责深色主题的 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 团队使用控制对强大 Web 平台功能的访问权限中定义的核心原则(包括用户控制、透明度和人体工学)设计和实现了用户偏好媒体功能客户端提示标头。
HTTP 客户端提示的安全注意事项和客户端提示可靠性的安全注意事项同样适用于此提案。
参考
- 规范草稿
- 说明
- Sec-CH-Prefers-Color-Scheme - Chrome 状态条目
- Sec-CH-Prefers-Color-Scheme - Chromium bug
- Sec-CH-Prefers-Reduced-Motion - Chrome 状态条目
- Sec-CH-Prefers-Reduced-Motion - Chromium bug
- WebKit 线程
- Mozilla 标准立场
- 客户端提示
- 客户端提示可靠性
- 媒体查询级别 5
- 适用于 HTTP 的结构化标头
致谢
非常感谢 Yoav Weiss 提供宝贵的反馈和建议。主打图片由 Tdadamemd 在 Wikimedia Commons 上提供。